React Props에 대해서

최재홍·2022년 7월 8일
0

HTML태그에 속성을 부여하여 스타일 제어를 하는 방법에는 세가지가 있었다.

1. 인라인 스타일(Inline Style)
2. 내부 스타일 시트(Internal Style Sheet)
3. 외부 스타일 시트(External Style Sheet)

이 중에서 HTML문서상에서 태그 <>안에 직접적으로 스타일을 지정하여 사용했던 것이 인라인 스타일이다.

ex) <p style='color : black' font-size : 15px>

JavaScript React에서 같은 방식으로 컴포넌트에 속성을 부여하여 제어하는데 도움을 주는 것이 이 'Props'이다.

  • props : properties(속성)
  • 단어의 뜻 그대로 컴포넌트의 속성값을 의미한다.
  • props는 상위 컴포넌트로부터 전달 받은 데이터를 지니고 있는 객체이다.
  • props를 이용해 어떤 타입의 자바스크립트 값이든 모두 하위 컴포넌트에 전달할 수 있다.

이러한 컴포넌트 구성이 있다고 가정해보자.

import './App.css';

function Header() {
	return <header>
	  <h1><a href="/">WEB</a></h1>
	</header>
}

function App() {
	return (
	  <div>
		<Header></Header>
		<Nav></Nav>
		<Article></Article>
	  </div>
	);
}

export default App

만약 우리가 <Header> 컴포넌트에 <h1>태그로 기입된 "WEB"이라는 문자열을 직접적으로 조작하지 않고, 변경사항이 있을 때마다 일괄적으로 제어할 수 있다면 편리할 것이다.

이럴 때,

function App() {
	return (
	  <div>
		<Header title="REACT"></Header>
		<Nav></Nav>
		<Article></Article>
	  </div>
	);
}

이렇게 상위 컴포넌트인 <App> 에서 <Header>라는 '컴포넌트'에 대해 마치 HTML에서 해당 '태그'에 속성값을 부여하듯이 'type'이라는 props를 부여할 수가 있다.

그리고 하위 컴포넌트인 <Header>에서

function Header(props) {
	return <header>
	  <h1><a href="/">{props.title}</a></h1>
	</header>
}

이렇게 해당 컴포넌트 함수에서 props라는 인자를 받아 상위 컴포넌트에서 부여한 속성값을 활용할 수가 있게 된다.

여기서 주의해야 할 점은 상기의 <a>태그 사이에 그냥 props.title이라고 기록하게 되면 일반적인 문자열로 간주되기 때문에 반드시 '{ }' 속에 기록하여 일반적인 문자열이 아닌 일종의 표현식임을 명시하는 것이다.

그리고 본 문서의 최상단에 명시된 것처럼 props는 상위 컴포넌트로부터 전달받은 데이터를 지니고 있는 '객체'이기 때문에 "props.title"과 같은 방식으로 표기하여야 한다.

"props"라는 객체 데이터의 "title"이라는 속성을 활용하겠다는 의미이기 때문이다.

상기에 예시는 결과적으로 <App>이라는 상위 컴포넌트에서 <Header>컴포넌트에 부여된 "title"이라는 속성과 "REACT"라는 속성값이 객체의 형태로 <Header>라는 하위 컴포넌트에 전달된다.
그리고 <Header>컴포넌트는 함수의 인자 형태로 전달받은 "props"라는 객체에서 "title"이라는 속성과 그에 부여된 "REACT"라는 속성값을 활용하고 싶기 때문에 객체인 "props"의 특정 속성을 "{props.title}"이라는 형태로 호출하여 마치 <h1>태그속에 "REACT"라는 문자열이 표기된 것처럼 화면에 출력할 수 있게 된다.

이해가 잘 되지 않을 때마다 상기의 인용문박스에 순차적으로 밝힌 과정을 반복적으로 읽어보도록 하자.


function App() {
	return (
	  <div>
		<Header title="REACT"></Header>
		<Nav></Nav>
		<Article title="Welcome" body="Hello, WEB"></Article>
        <Article title="Hi" body="Hello, React"></Article>
	  </div>
	);
}

한편, 당연한 이야기지만 상기의 예시에서 <Header>, <Article>이라는 두 컴포넌트에 모두 속성과 속성값이 부여됐듯이 여러 하위컴포넌트에 대해서 다중적으로 속성과 속성값을 부여하는 것도 문제가 없다.

또한 <Aricle>이라는 하나의 컴포넌트에 "title", "body"와 같은 다중적인 속성과 속성값을 부여하는 것도 문제가 없다.

"props는 상위 컴포넌트에서 전달받은 데이터를 담고 있는 객체로서 함수의 인자로 활용된다."

는 말을 늘 상기하자.
 


function Nav() {
return <nav>
       <ol>
         <li><a href="/read/1">html</a><li>
         <li><a href="/read/2">css</a><li>
         <li><a href="/read/3">js</a><li>
       </ol>
     </nav>
	);
}

이러한 <Nav>라는 이름의 컴포넌트가 구성되어 있다고 생각해보자. <li>태그에 변동이 생길 때마다 <Nav> 컴포넌트에 대해서 직접적으로 제어를 하는 대신 <App>에서 <Nav>에 주입된 props값에 따라서 유동적으로 데이터가 변화할 수 있다면 편리할 것이다.

function App() {
  const topics = [
	{id:1, title:'html', body:'html is...'},
	{id:2, title:'css', body:'css is...'},
	{id:3, title:'js', body:'js is...'}
]
	return (
	  <div>
		<Header title="REACT"></Header>
		<Nav topics={topics}></Nav>
		<Article title="Welcome" body="Hello, WEB"></Article>
      <Article title="Hi" body="Hello, React"></Article>
	  </div>
	);
}

기존에 <App>컴포넌트에 대해서 코딩된 내용에서의 변경점이 두가지가 있는데 첫번째는 "topics"라는 이름의 변수가 선언되어 객체데이터들로 이루어진 배열이 할당되었고, 두번째는 <App>에서 <Nav>컴포넌트에 "topics"라는 props의 속성과 속성값을 부여하였다.

function Nav(props) {
  const lis = [
  <li><a href="/read/1">html</a></li>,
  <li><a href="/read/2">css</a></li>,
  <li><a href="/read/3">js</a></li>
  ]
  return <nav>
    <ol>
      {lis}
    </ol>
  </nav>
  }

현 상태에서는 상위 컴포넌트에서 props라는 객체 데이터를 받아 함수의 인자로 활용하였지만 함수 내부에서 아무런 쓰임도 받지 못 하고 있다.

function Nav(props) {
const lis = []
for(let i=0; i<props.topics.length; i++) {
     let t = props.topics[i];
     lis.push(<li><a href={'/read/'+t.id}>{t.title}</a></li>)
}
return <nav>
  <ol>
    {lis}
  </ol>
</nav>
}

이렇게까지 코딩을 했을 때, 비로소 상위 컴포넌트로부터 전달받은 "topics"라는 속성에서 "topics"라는 속성값을 받아 그 "topics"라는 속성값으로 쓰인 같은 변수 "topics"에 할당된 객체 데이터를 활용할 수 있게 된다.

<Nav>는 "for"반복문을 통해 0부터 topics라는 배열의 길이에 닿을때까지 "topics"라는 배열의 각 요소에 차례대로 접근하여 요소들을 "lis"라는 빈 배열에 push하게 된다.

props를 통해서 컴포넌트간 동적 상호작용을 작동시킬 수 있게 된 것이다.

하지만 코드를 동작시키면 다음과 같은 경고문을 보게 되는데

Warning: Each child in a list should have a unique "key" prop.
경고 : 리스트에 생성된 자식 <li>태그들은 "key"라고 하는 각각의 고유한 prop을 지녀야 한다.

따라서 마지막 작업으로 <Nav> 컴포넌트에 동적으로 생성되게 될 <li>태그들에 대해서 고유한 "key"라는 prop을 부여해야 한다.

lis.push(<li key={t.id}><a href={'/read/'+t.id}>{t.title}</a></li>)

0개의 댓글