props에 대해 배워보자!
#4.0 ~ 4.3
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Document</title>
</head>
<body>
<div id="root"></div>
</body>
<script src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script type="text/babel">
function App() {
return (
<div></div>
);
}
const root = document.getElementById("root");
ReactDOM.render(<App />, root);
</script>
</html>
App
컴포넌트만 남김function SaveBtn() {
return (
<button style={{
backgroundColor: "tomato",
color: "white",
padding: "10px 20px",
border: 0,
borderRadius: 10,
}}>Save Changes</button>
);
}
function ConfirmBtn() {
return (
<button style={{
backgroundColor: "tomato",
color: "white",
padding: "10px 20px",
border: 0,
borderRadius: 10,
}}>Confirm</button>
);
}
function App() {
return (
<div>
<SaveBtn />
<ConfirmBtn />
</div>
)
}
style
속성이 똑같은데 두 버튼 다 똑같이 쓰면 코드의 가독성이 떨어지고, 이런 것들이 많아지면 나중에 파일의 크기도 커질 위험이 있음. 또한 오타 등의 오류를 행할 수 있고, 유지보수가 어렵다.function Btn(props) {
console.log(props);
return (
<button style={{
backgroundColor: "tomato",
color: "white",
padding: "10px 20px",
border: 0,
borderRadius: 10,
}}>
{props.banana}
</button>
);
}
function App() {
return (
<div>
//밑의 코드는 Btn({banana="Save Changes", x={false}}) 랑 똑같음
<Btn banana="Save Changes" x={false} />
<Btn banana="Continue" y={7} />
</div>
)
}
Btn
이라는 함수컴포넌트로 캡슐화, 추상화 시켜줌.banana
에 값을 넣어서 그 값을 읽어주는 방식으로 함.props
임. Btn으로부터 전달 받는 properties 라는뜻
💡 props를 console.log() 해보면 하나의 객체로 받는걸 알 수있음.
function Btn({banana}) {
// console.log(props); //Save Changes //Continue
return (
<button style={{
backgroundColor: "tomato",
color: "white",
padding: "10px 20px",
border: 0,
borderRadius: 10,
}}>
{banana}
</button>
);
}
banana
는 객체라서 객체를 바로 불러와준다.function Btn({text, big}) {
console.log({text, big});
return (
<button style={{
backgroundColor: "tomato",
color: "white",
padding: "10px 20px",
border: 0,
borderRadius: 10,
}}>
{text}
</button>
);
}
function App() {
return (
<div>
<Btn text="Save Changes" x={false} big={true} />
<Btn text="Continue" y={7} /> //속성이름은 아무거나 해도됨
</div>
)
}
function Btn({banana, big}) {
console.log(banana, big);
return (
<button style={{
backgroundColor: "tomato",
color: "white",
padding: "10px 20px",
border: 0,
borderRadius: 10,
fontSize: big ? 18 : 12, //여기
}}>
{banana}
</button>
);
}
function App() {
return (
<div>
<Btn banana="Save Changes" x={false} big={true} />
<Btn banana="Continue" y={7} big={false} />
</div>
)
}
big
이라는 속성으로 big
이 true면 18px : false면 12px 이런 식으로도 작성 가능function Btn({text, onClick}) {
return (
<button
onClick={onClick}
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>
{ // 밑의 onClick은 이벤트 리스너가 아니고 그냥 props임
// onClick이벤트는 커스텀 컴포넌트에 넣을수 없고 HTML태그 안에 넣야함
}
<Btn text={value} onClick={changeValue} />
<Btn text="Continue" />
</div>
)
}
<Btn text="Continue" />
는 리렌더링 될 필요없는데 같이 리렌더링이 됨.<div>
<Btn text={value} onClick={changeValue} />
<Btn text="Continue" /> // 리렌더될 필요 없는데 같이 리렌더됨.
</div>
💡React.memo()
를 사용해서 props가 변경되지 않는다면 다시 그릴 필요가 없다는 것을 알려줘야함.
function Btn({ text, onClick }) {
console.log(text, 'was rendered');
return (
<button
onClick={onClick}
style={{
backgroundColor: "tomato",
color: "white",
padding: "10px 20px",
border: 0,
borderRadius: 10,
}}>
{text}
</button>
);
}
const MemorizedBtn = React.memo(Btn);
function App() {
const [value, setValue] = React.useState("Save Changes");
const changeValue = () => setValue('Revert Changes')
return (
<div>
<MemorizedBtn text={value} onClick={changeValue} />
<MemorizedBtn text="Continue" />
// 리렌더링 해야할 컴포넌트가 많아지면 이렇게 변화된 것만 리렌더링 되게끔 해줘야 함.
</div>
)
}
const MemorizedBtn = React.memo(Btn);
작성하고 커스텀 컴포넌트의 이름을 변경해줌.만약 협업에서 같이 일하는 사람이 많아질수록, 나만 코드를 작성하는 것이 아니고, 실수를 할 수 있기 때문에 타입 오류를 검사할 수 있는 코드를 작성을 하는 것도 중요함.
function App() {
return (
<div>
<Btn text="Save Changes" fontSize={18} />
<Btn text={14} fontSize={"Continue"} />
</div>
);
}
💡 이럴때 리액트에서 PropTypes
라는 이름의 패키지로 타입을 검사할 수 있음
PropTypes
라고 입력하면 어떤 타입을 검사해줄지 볼 수있음development.js
버전으로 바꾸고 prop-types 링크도 넣어줌. <script src="https://unpkg.com/react@17.0.2/umd/react.development.js "></script>
<script src="https://unpkg.com/prop-types@15.7.2/prop-types.js"></script>
function Btn({ text, fontSize = 14 }) {
return (
<button
style={{
backgroundColor: "tomato",
color: "white",
padding: "10px 20px",
border: 0,
borderRadius: 10,
fontSize,
}}
>
{text}
</button>
);
}
Btn.propTypes = {
text: PropTypes.string,
fontSize: PropTypes.number,
};
// text는 string, fontSize는 number로 지정해줌
function App() {
return (
<div>
<Btn text="Save Changes" fontSize={18} />
<Btn text={14} fontSize={"Continue"} />
</div>
);
}
.propTypes
로 text는 string, fontSize는 number로 지정해줌안지키면 아래처럼 경고가 뜸.
아래처럼 수정하니 오류가 사라짐!
.isRequired
를 작성해줌 Btn.propTypes = {
text: PropTypes.string.isRequired, //여기
fontSize: PropTypes.number,
};
function App() {
return (
<div>
<Btn text={"Save Changes"} fontSize={18} />
<Btn fontSize={14} />
</div>
);
}
.isRequired
를 작성해 준 속성(여기선 text)이 없으면 경고가 뜸.function Btn({ text, fontSize = 14 }) {
return (
<button
style={{
backgroundColor: "tomato",
color: "white",
padding: "10px 20px",
border: 0,
borderRadius: 10,
fontSize,
}}
>
{text}
</button>
);
}
Btn.propTypes = {
text: PropTypes.string.isRequired, //isRequired 속성을 줌
fontSize: PropTypes.number,
};
function App() {
return (
<div>
<Btn text={"Save Changes"} fontSize={18} />
<Btn text={"Revert Changes"} fontSize={14} />
</div>
);
}
{ text, fontSize = 14 }
이렇게 작성해주면 폰트사이즈 속성에 value가 없을때 자동으로 14px로 적용됨.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Document</title>
</head>
<body>
<div id="root"></div>
</body>
<script src="https://unpkg.com/react@17.0.2/umd/react.development.js "></script>
<script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/prop-types@15.7.2/prop-types.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script type="text/babel">
function Btn({ text, fontSize = 14 }) {
return (
<button
style={{
backgroundColor: "tomato",
color: "white",
padding: "10px 20px",
border: 0,
borderRadius: 10,
fontSize,
}}
>
{text}
</button>
);
}
Btn.propTypes = {
text: PropTypes.string.isRequired, //isRequired 속성을 줌
fontSize: PropTypes.number,
};
function App() {
return (
<div>
<Btn text={"Save Changes"} fontSize={18} />
<Btn text={"Revert Changes"} fontSize={14} />
</div>
);
}
const root = document.getElementById("root");
ReactDOM.render(<App />, root);
</script>
</html>