#4 PROPS
4.0 PROPS
저번 시간에 배운것
const [amount, setAmount] = React.useState(0);
const onChange = (event) => {
setAmount(event.target.value);
}
{index === "xx" ? "Please select your units": null}
오늘
Props : 부모컴포넌트로부터 자식컴포넌트에 데이터를 보낼 수 있게 해주는 방법
우리가 만드는 컴포넌트들은 괄호로 인자를 받아온다. 인자를 props, properties라고 부름
ex) 같은 스타일의 버튼 여러개를 만들때 버튼 하나하나에 스타일을 복붙하는것은 낭비. 그것을 해결해보려 함
리엑트가 프롭들을 자동으로 넣어주어, 내가 사전자료형처럼 넣는 효과라고 보면 됨
Btn({banana:"save changes"}) <!-- 이론상 아래와 동일함 -->
<Btn banana="Save Changes" />
여러개의 인자를 보낼 수도 있음.
<!DOCTYPE html>
<html>
<body>
<div id="root"></div>
</body>
<script type="text/babel">
const root = document.getElementById("root");
/*function Btn(props){ //사전자료형으로 보내는 것이기 때문에, 바나나든 text든 상관 없음
console.log(props);
return (
<button style={{
backgroundColor: "tomato",
color:"white",
padding:"10px 20px",
border: 0,
borderRadius: 10,
}}>
{props.banana}
</button>
);
}*/
function Btn({text, big}){
console.log({text, big}); // 그냥 지름길일 뿐이라 함. property를 오브젝트로부터 미리 꺼낸다
return (
<button style={{
backgroundColor: "tomato",
color:"white",
padding:"10px 20px",
border: 0,
borderRadius: 10,
fontSize: big ? 18 : 16, // 삼항연산자
}}>
{text}
</button>
);
}
function App(){
return (
<div>
<Btn text="Save Changes" x={false} big={true} />
<Btn text="Continue" y={7} />
</div>
);
}
ReactDOM.render(<App />, root);
</script>
</html>
=====================================================================
4.1 Memo
html태그에 쓰는 onClick과 JSX
html소스가 들어가는 부분에 쓴 것은 이벤트리스너를 등록하는 것이 맞으나,
커스텀 컴포넌트에 onClick을 넣는것은 이벤트리스너를 등록하는것이 아님. 완전히 다르다고 볼 수 있음
<div>
<Btn text="Save Changes" onClick={changeValue} />
<Btn text="Continue" />
</div>
onClick리스너로 쓰일꺼라고 이름을 onClick으로 둘 필요는 없음
function Btn({text, changeValue}){
return (
<button
onClick={changeValue}
return (
<div>
<Btn text={value} changeValue={changeValue} />
<Btn text="Continue" />
</div>
);
prop으로 넣는다고 자동으로 들어가지 않음. 직접 넣어줘야함
<!DOCTYPE html>
<html>
<body>
<div id="root"></div>
</body>
<script type="text/babel">
const root = document.getElementById("root");
function Btn({text, changeValue}){
console.log(text, "was rendered");
return (
<button
onClick={changeValue}
style={{
backgroundColor: "tomato",
color:"white",
padding:"10px 20px",
border: 0,
borderRadius: 10,
}}>
{text}
</button>
);
}
function App(){
const [value, setValue] = React.useState("Save Changes");
const changeValue = () => setValue("Revert Changes");
return (
<div>
<Btn text={value} changeValue={changeValue} />
<Btn text="Continue" />
</div>
);
}
ReactDOM.render(<App />, root);
</script>
</html>
//버튼을 여러번 눌러도 state는 한번만 바뀌어서 여러번 동작하지는 않는군.
내부 value값이 그대로라 변할 필요가 없는 Continue도 render되는것을 알 수 있다.
이는 낭비로 보임.
그래서 React Memo가 필요함
<!DOCTYPE html>
<html>
<body>
<div id="root"></div>
</body>
<script type="text/babel">
const root = document.getElementById("root");
function Btn({text, changeValue}){
console.log(text, "was rendered");
return (
<button
onClick={changeValue}
style={{
backgroundColor: "tomato",
color:"white",
padding:"10px 20px",
border: 0,
borderRadius: 10,
}}>
{text}
</button>
);
}
// 본래는 부모의 State가 변경되면 모든 자식이 리렌더 된다. 이게 느려지는 원인이 될 수도
// 리엑트에게 프롭이 변하지 않는다면 바꾸지 말아주세요~ 하는 느낌이라고 함
const MemorizedBtn = React.memo(Btn);
function App(){
const [value, setValue] = React.useState("Save Changes");
const changeValue = () => setValue("Revert Changes");
return (
<div>
<MemorizedBtn text={value} changeValue={changeValue} />
<MemorizedBtn text="Continue" />
</div>
);
}
ReactDOM.render(<App />, root);
</script>
</html>
======================
4.2 Prop Types : 리액트가 우리에게 틀렸다고 말해준다
리엑트에게 우리 prop들의 type이 뭔지 알려준다
<!DOCTYPE html>
<html>
<body>
<div id="root"></div>
</body>
<script type="text/babel">
const root = document.getElementById("root");
function Btn({text, fontSize = 12}){ // 기본값
return (
<button
style={{
backgroundColor: "tomato",
color:"white",
padding:"10px 20px",
border: 0,
borderRadius: 10,
// fontSize: fontSize // 둘이 똑같으면 자동으로 맵핑되나봄... 이건 첨보네
fontSize,
}}>
{text}
</button>
);
}
// 대소문자 주의
Btn.propTypes = { //Btn.propTypes
text: PropTypes.string.isRequired, //PropTypes.string
fontSize: PropTypes.number, //isRequired가 걸린 애들은 반드시 필요함
};
function App(){
return(
<div>
<Btn text="Save Changes" fontSize={18} />
<Btn text="Continue" />
</div>
);
}
ReactDOM.render(<App />, root);
</script>
</html>
==================================
4.3 Recap(요약)
1. type script는 해당하지 않지만, 인자(prop)으로 받아올 데이터형을 지정하여 오류에 대한 경고를 띄워줄 수 있음.
2. react memo를 활용해, 이미 랜더링된것과 차이가 없는 자식 컴포넌트는 다시 랜더하지 않도록 할 수 있음.