💡 Props로 컴포넌트에 값에 접근하고, memo를 이용해 변하는 것만 리렌더링 되게끔 하는 것을 구현하는 방법을 공부해보자!
<!DOCTYPE html>
<html>
<body>
<div id="root"></div>
</body>
<!-- React JS는 어플리케이션이 아주 interactive하도록 만들어주는 library
-> 엔진, interactive한 UI만들게 해줌
-->
<script crossorigin src="https://unpkg.com/react@17/umd/react.production.min.js"></script>
<!-- React-dom은 library또는 package인데, 모든 react element들을 HTML body에 둘 수 있도록 해줌 -->
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script>
<!-- jsx를 browser가 읽을 수 있게 babel을 이용해서 변환 -->
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script type="text/babel">
const root = document.getElementById('root');
function App() {
return <div></div>
}
ReactDOM.render(<App />, root);
</script>
</html>
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="Continue" y={7} />
</div>
)
}
Btn
이라는 함수로 캡슐화, 추상화 시켜주었다.banana
에 값을 넣어서 그 값을 읽어주는 방식으로 했다.function Btn({banana}) {
// console.log(props);
return (
<button style={{
backgroundColor: "tomato",
color: "white",
padding: "10px 20px",
border: 0,
borderRadius: 10,
}}>
{banana}
</button>
);
}
banana
는 객체라서 객체를 바로 불러와준다.{banana}
이런식으로 적어주면 된다.function Btn({banana, big}) {
console.log({banana, big});
return (
<button style={{
backgroundColor: "tomato",
color: "white",
padding: "10px 20px",
border: 0,
borderRadius: 10,
}}>
{banana}
</button>
);
}
function App() {
return (
<div>
<Btn banana="Save Changes" x={false} big={true} />
<Btn banana="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,
cursor:'pointer',
}}>
{text}
</button>
);
}
function App() {
const [value, setValue] = React.useState("Save Changes");
const changeValue = () => setValue('Revert Changes')
return (
<div>
{
// 커스텀 컴포넌트에 들어가는 onClick은 이벤트 리스너가 아니다! 그냥 prop
// Btn 함수 안에 button 태그안에 들어가는 것이 이벤트 리스너이다.
}
<Btn text={value} onClick={changeValue} />
<Btn text="Continue" />
</div>
)
}
Btn
함수에 들어가 있는 onClick
이 진짜 이벤트 리스너이고, 커스텀 컴포넌트에 있는 onClick
은 그냥 props이다.<Btn text="Continue" />
는 리렌더링 안되어도 되는데 리렌더링이 같이 되어버린다. 만약 코드가 길어지면 리렌더링 굳이 하지 않아도 되는데 리렌더링 하면 안좋다. 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,
cursor: 'pointer',
}}>
{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} />
{
// props가 변하지 않으면 리렌더링 안되게 할 수 있다.
// 하지만 props값이 바뀌면 리렌더링 해줘야한다.
// 리렌더링 해야할 컴포넌트가 많아지면 이렇게 변화된 것만 리렌더링 되게끔 해줘야한다.
}
<MemorizedBtn text="Continue" />
</div>
)
}
const MemorizedBtn = React.memo(Btn);
작성해주고, 커스텀 컴포넌트의 이름을 변경해준다. function App() {
const [value, setValue] = React.useState("Save Changes");
const changeValue = () => setValue('Revert Changes')
return (
<div>
<MemorizedBtn text={value} fontSize={30} />
{
// 아래 문장은 문법 상에 문제는 없지만, 의미상의 문제가 있다.
// 화면에는 오류 없이 보여지지만 오류인 것이다.
// 오류를 확인할 수 있는 코드를 만들면 좋을 것 같다.
}
<MemorizedBtn text={14} fontSize={"Continue"} />
</div>
)
}
development.js
로 바꿔줘야 한다.<script crossorigin src="https://unpkg.com/react@17.0.2/umd/react.development.js"></script>
function Btn({ text, fontSize }) {
return (
<button
style={{
backgroundColor: "tomato",
color: "white",
padding: "10px 20px",
border: 0,
borderRadius: 10,
cursor: 'pointer',
fontSize,
}}>
{text}
</button>
);
}
Btn.propTypes = {
text: PropTypes.string,
fontSize: PropTypes.number,
};
function App() {
const [value, setValue] = React.useState("Save Changes");
const changeValue = () => setValue('Revert Changes')
return (
<div>
<Btn text={value} fontSize={30} />
<Btn text={14} fontSize={"Continue"} />
</div>
)
}
text
는 string
, fontSize
는 number
로 지정해줬다..isRequired
를 작성해준다. Btn.propTypes = {
text: PropTypes.string.isRequired,
fontSize: PropTypes.number,
};
function App() {
const [value, setValue] = React.useState("Save Changes");
const changeValue = () => setValue('Revert Changes')
return (
<div>
<Btn text={value} fontSize={30} />
<Btn fontSize={14} />
</div>
)
}
.isRequired
를 작성해 준 속성이 없으면 경고 문구가 뜬다. function Btn({ text, fontSize = 12 }) {
return (
<button
style={{
backgroundColor: "tomato",
color: "white",
padding: "10px 20px",
border: 0,
borderRadius: 10,
cursor: 'pointer',
fontSize,
}}>
{text}
</button>
);
}
Btn.propTypes = {
text: PropTypes.string.isRequired,
fontSize: PropTypes.number,
};
function App() {
const [value, setValue] = React.useState("Save Changes");
const changeValue = () => setValue('Revert Changes')
return (
<div>
<Btn text={value} fontSize={30} />
<Btn text={'Continue'} />
</div>
)
}
{ text, fontSize = 12 }
이렇게 작성해 주면, 폰트 사이즈 속성이 없으면 자동으로 12px이 적용이된다.