한 개의 component에 같은 component를 여러번 사용하고 사용한 부모의 component에서 state의 변경이 일어나 re-rendering하게 된다면 다른 component들은 어떻게 될까?
const Btn = ({ text, changeValue }) => {
console.log(text, 'was rendered');
return <button onClick={changeValue}>{text}</button>
};
라는 Btn component가 존재하고 1번 버튼에는 클릭시 'btn1'에서 'btn2'로 innerText가 바뀌는 이벤트처리 함수와 innerText를 props로 넘겨주었다고 하자.
console.log()부분은 버튼이 rendering되는 것을 확인하기 위한 부분이다.
const App = () => {
const [value, setValue] = React.useState('btn1');
const changeValue = (event) => {
setValue(event.target.innerText === 'btn1' ? 'not btn1' : 'btn1');
};
return (
<>
<Btn text={value} changeValue={changeValue} />
<Btn text='btn2' />
</>
);
그리고 다음과 같이 2개의 버튼을 선언하였다.
첫 실행시 2개의 버튼이 전부 render된것을 확인할 수 있다.
이후 btn1을 클릭하게 된다면 changeValue함수로 인해 not btn1으로 바뀌면서 re-rendering하게 된다.
그리고 console에는 "not btn1 was rendered."만 출력되어야한다.
하지만 결과는 그렇지 않았다. 어떤 텍스트나 state의 변경이 없었던 btn2도 같이 rendering된 것이다.
이것은 두 개의 부모 component인 App component의 state가 변경되었기때문에 App component가 re-rendering되면서 같이 rendering하기 때문이다. 이렇게 코드를 작성하면 Btn의 수가 많아지게 될수록 전체 rendering이 이루어지기 때문에 성능이 저하될 수 있다.
이럴때 React.memo()를 사용할 수 있다. 함수의 인자로 component를 주면 함수는 새로운 component를 반환하게되고 개발자는 이것을 새로운 변수에 저장해 사용하면 된다.
const App = () => {
const [value, setValue] = React.useState('btn1');
const changeValue = (event) => {
setValue(event.target.innerText === 'btn1' ? 'not btn1' : 'btn1');
};
const MemorizedBtn = React.memo(Btn); // 변경된 부분
return (
<>
// 변경된 부분
<MemorizedBtn text={value} changeValue={changeValue} />
<MemorizedBtn text='btn2' />
</>
);
버튼 component를 <Btn />
에서 React.memo()의 결과로 받은 새로운 component인 <MemorizedBtn />
으로 변경해주었다. 그리고 나서 다시 한번 state를 변경하면
사진을 보면 우리가 원하던 결과인 not btn1만 rendered된 것을 확인할 수 있다.
위처럼 memo를 사용하게 되면 부모인 App component를 re-rendering하더라도 btn1 props로 주어진 value의 state만 변하기 때문에 btn1만 re-rendering된다.
이처럼 임의의 component에서 state의 변경이 일어난다면 하위 모든 component가 re-rendering이 일어나게 된다. 이를 방지하기 위해 개발자는 React.memo(component)
를 이용해 인자로 전달한 component의 props가 변경됀 것만 다시 rendering하게 만들 수 있다.