리엑트에선 props라는 개념을 도입해서 사용한다.
properties, 속성이라는 뜻으로 html에서와 같이 요소가 가질 수 있는 속성이 있고 그 속성값에 따라 요소에 접근할 수 있듯이
리엑트도 이와 비슷한 개념으로 써 그 속성을 "props"라고 표현하고 있는것이다.
props를 사용해서 사용자 지정 컴포넌트(직접 만든 컴포넌트)에 적용할 데이터를 전달 할 수 있다.
컴포지션이란,
작은 빌딩 블럭으로부터 사용자 인터페이스를 구축하는 접근 방법을 일반적으로 합성(컴포지션)이라고 부른다.
여기서 중요한 부분은, 경우에 따라서
우리가 props를 통해 모든것을 설정해서 전달하는 컴포넌트가 아니라 컴포넌트의 열고 닫는 태그 사이의 컨텐츠를 전달하고 싶을 수도 있다.
이때 사용하는게 children props인데
리엑트에서 children props는 보통 래퍼 컴포넌트에서 활용하게 된다.
내장된 props로써 사용하게 될때, 해당 래퍼 컴포넌트에 props로 children을 사용하지 않은채 적용하게 된다면 사용자 지정 컴포넌트를 컨텐츠로 하여금 감쌀 수 없게 된다.
해당 래퍼컴포넌트 안에서 감쌀 컨텐츠(컴포넌트 혹은 요소들)를 모두 children이라고 생각하여 적용 시켜야한다.
function Card(props) {
return <div className="card">{props.children}</div>;
}
export default Card;
Card컴포넌트 즉, 함수 안에 있는 열고 닫는 div태그 안에서 이뤄지는 모든것들이 바로 props.children이고 이는 여기서 Card컴포넌트안에 들어간 컴포넌트나 html요소들을 전부 포함하여 합성된 코드들이다.
즉, 이 특별한 props.children의 값은 언제나 사용자 지정 컴포넌트에 열고 닫는 태그 사이에 있는 컨텐츠이다.
단, 주의사항이 있다.
위처럼 적용했을때 지정한 래퍼컴포넌트인 Card.js를 다른 컴포넌트에서 사용하려 해도 해당 속성이 적용되어 나타나지 않을 것이다.
리엑트에서 래퍼컴포넌트로 설정한 컴포넌트에서는 일반 html요소에서 props로 클래스 이름을 설정하는것과 다르게 props로 직접 className을 설정할 수 없다. 왜냐하면 우리가 만든 사용자 지정 컴포넌트엔 className을 지원하지 않기 때문이다.
만약 위 예시에서 Card컴포넌트에 className이 설정되길 원한다면,
직접 문자열로 바꾸어 적용하는 방법을 사용해보면 된다.
// 변경 후
function Card(props) {
const classes = `card ${props.className}`
return <div className={classes}>{props.children}</div>;
}
export default Card;
이렇게 다른 컴포넌트에서 props로 받아오는 className은 문자열로 추가된다.
그래야 div 요소의 "card" 클래스와 props.className의 영향을 동시에 받아 취할 수 있게 된다.