리액트 props
props란 부모 컴포넌트가 자식 컴포넌트에게 값을 전달할 수 있는 기능을 말한다.
만약 여러 군데 반복적으로 사용될 버튼을 만들려면 컴포넌트를 만드는 게 좋다
[Button.jsx]
import './Button.css';
export default function Button(){
return <button className='button'>클릭</button>
}
버튼이 자주 사용될 것 같은 요소라서 컴포넌트로 만들어두긴 했지만, 문제는 버튼 안에 표시되는 “클릭”을 버튼마다 다르게 할 수가 없다는 점이다.
모양은 똑같지만 나타나는 글자를 다르게 하려면 자식 컴포넌트에게 데이터를 보내주는 기능인 props를 사용해야한다.
[Body.jsx]
import Button from './Button'
export default function Body(){
return(
<div className='body'>
<h1>Body</h1>
<Button text={'1번 버튼'}/>
<Button/>
<Button />
</div>
)
}
위에서 Button 컴포넌트를 Body 컴포넌트의 자식 컴포넌트로 배치하고 있는데, 이때 Button 컴포넌트 안에 전달해주고 싶은 값을 같이 써준다. 버튼 안의 텍스트를 나타내기 위해서는 text={‘1번 버튼’}을 전달하는 것이다. 이렇게 자식 컴포넌트에게 전달한 text 같은 값을 props라고 부른다.
Button 컴포넌트는 자신의 부모, 즉 Body 컴포넌트로부터 전달받은 text={‘1번 버튼’}라는 값(props)을 불러다가 사용할 수 있게 된다.
전달받은 값을 사용하는 법은 다음과 같다
export default function Button(props){
console.log(props)
return <button className='button'>버튼</button>
}
Button 컴포넌트로 이동해서 매개변수 props를 선언한다.
매개변수 props에는 어떤 값이 전달되는지 확인해 보기 위해 console.log(props)를 찍어보면, 객체 3개가 console에 출력된 것을 확인할 수 있다. 객체 3개가 출력된 이유는 Body 컴포넌트에서 Button 컴포넌트 3개를 렌더링 하기 때문에 Button 컴포넌트가 3번 호출된 것이다. 컴포넌트가 렌더링 된다는 건, 그냥 이 함수가 호출된다라고 이해할 수 있다.
Body 컴포넌트의 첫 번째 버튼의 Object를 눌러보면 text: “1번 버튼”이라는 값이 프로퍼티로 들어있음을 확인할 수 있다. 두 번째, 세 번째 버튼은 아무것도 전달하지 않았으므로 아무것도 들어있지 않다.
정리)
부모컴포넌트에서 자식컴포넌트로 text={“1번 버튼”}라는 값을 전달하는 것을 props라고 부른다. 이 값은 자식 컴포넌트에서 매개변수로 받아올 수 있고, 전달한 값들이 객체에 묶여서 프로퍼티에 하나씩 보관이 되어서 전달이 된다.
자식 컴포넌트에서 선언한 매개변수로 객체가 들어오는데, 그 객체에는 부모컴포넌트에서 전달한 prop 값들이 프로퍼티로 묶여있는 것!
객체로 들어오는 프로퍼티 값을 점표기법을 활용해서 위처럼 사용하면
부모컴포넌트에서 전달한 값이 잘 적용됨을 알 수 있다.
만약 색을 바뀌게 하는 color 속성을 추가하면
잘 적용된다 헤헷
[props를 이용하는 다양한 방법, 응용팁 ]
1. 구조 분해 할당
export default function Button(props){
const {color, text} = props;
return <button
style={{
backgroundColor: color
}}
className='button'>
{text}
</button>
}
const {color, text} = props;
구조분해 할당을 통해 props에 들어있는 객체 프로퍼티를 각각 color, text 변수에 꺼내놓으면 props.color으로 쓰던 것을 그냥 color로 써도 된다.
export default function Button({color,text}){
return <button
style={{
backgroundColor: color
}}
className='button'>
{text}
</button>
}
export default function Button({color, text})
위처럼 매개변수 자체에서 구조분해할당을 바로 받을 수도 있다.
2. 부모 컴포넌트에서 값을 전달할 때 깔끔하게 전달하는 방법
return문은 해당 컴포넌트가 어떻게 생긴 UI를 표현할 것인지를 나타내는 부분이기에, return문 내부만 봐도 '어떤 컴포넌트를 렌더링 하겠구나'를 알 수 있어야 한다. 그래서 리액트에서는 return 내부를 길게 작성하는 것을 피하는 경향이 있다.
그런데 위처럼 props를 너무 길게 연달아 전달하면 가독성이 안 좋아진다.
이때, 깔끔하게 전달하는 방법이 있다.
바로 전달하는 것이 아니라, 따로 변수를 만들고, 객체로 전달할 props들을 저장해 준다. 그리고 스프레드연산자(전개연산자)를 통해 buttonProps 변수에 담긴 프로퍼티들을 하나하나씩 흩뿌려서 전달한다.
이렇게 하면 아까보다 깔끔하게 return문 내부를 유지할 수 있다. 가독성 측면에서는 상당한 도움이 될 수 있다.
3. props에 HTML 태그, 리액트 컴포넌트 전달
셀프 클로징이 아닌, 닫는 태그를 만들면, 위의 <div> 같은 HTML 요소를 <Button>의 자식요소로 배치할 수 있다.
<Button> 컴포넌트 사이의 자식요소는 <Button> 요소에게 children라는 props로 전달된다.
<Button> 컴포넌트에서 위의 <div> 같은 값을 전달받아서 사용하려면 children 매개변수를 선언해 준다.
그리고 children 값을 렌더링 하게 하면, children 값이 전달된 첫 번째 버튼에<div> 버튼 </div>가 잘 전달된 것을 확인할 수 있다.
위와 마찬가지로 리액트의 컴포넌트도 전달할 수 있다