컴포넌트가 rendering 된다는 것은 함수가 호출되는 것을 의미한다. 함수를 다시 호출하면, 연산도 다시 할 뿐만 아니라, 함수도 다시 정의된다. 다시 연산되는것을 막기 위해 useMemo를 사용했고, 함수가 다시 정의되는 것을 막기 위해 useCallback을 사용한다.
import { useState } from 'react';
import './App.css';
import CheckBox from './components/CheckBox';
function App() {
const [foodOn, setFoodOn] = useState(false);
const [clothOn, setClothOn] = useState(false);
const [shelterOn, setShelterOn] = useState(false);
const foodOnChange = (e) => setFoodOn(e.target.checked);
const clothOnChange = (e) => setClothOn(e.target.checked);
const shelterOnChange = (e) => setShelterOn(e.target.checked);
return (
<div>
<CheckBox
label='Food'
on={foodOn}
onChange={foodOnChange}
/>
<CheckBox
label='Cloth'
on={clothOn}
onChange={clothOnChange}
/>
<CheckBox
label='Shelter'
on={shelterOn}
onChange={shelterOnChange}
/>
</div>
);
}
export default App;
import React from 'react';
const CheckBox = React.memo(({ label, on, onChange }) => {
console.log(label, on);
return (
<div>
<label>{label}</label>
<input type="checkbox" defaultChecked={on} onChange={onChange} />
</div>
);
});
export default CheckBox;
App 컴포넌트에서 checkbox를 눌러 state를 바꾸면 App 컴포넌트가 rendering 되고, 자식 컴포넌트인 CheckBox도 따라서 rendering 되야 하지만, CheckBox 컴포넌트에 React.memo를 사용했기 때문에 자식 컴포넌트인 CheckBox는 rendering이 안되야 한다. 하지만 console.log()를 찍어보면 CheckBox 컴포넌트도 re rendering이 된다.
그 이유는 무엇일까?
처음에 말했듯이 컴포넌트의 state가 변했기 때문에, 함수가 re rendering 된다. re rendering된다는 것은 컴포넌트 함수를 다시 호출한다는 것이고 연산 뿐만 아니라 함수를 재정의
한다.
예를 들어, Food checkbox를 눌렀을 경우, state가 변했기 때문에 App 함수를 다시 호출하고
const foodOnChange = (e) => setFoodOn(e.target.checked);
const clothOnChange = (e) => setClothOn(e.target.checked);
const shelterOnChange = (e) => setShelterOn(e.target.checked);
이 함수들을 재정의한다. 함수가 재정의 되었기 때문에 이 함수들은 이전의 함수와 다른 함수이고, CheckBox 컴포넌트에 새로운 props를 전달한다. CheckBox 컴포넌트는 새로운 props를 전달받았기 때문에, re rendering 된다.
이것을 막기 위해 useCallback이라는 hook을 사용한다.
const foodOnChange = useCallback((e) => setFoodOn(e.target.checked), []);
const clothOnChange = useCallback((e) => setClothOn(e.target.checked), []);
const shelterOnChange = useCallback((e) => setShelterOn(e.target.checked), []);
useCallback()을 사용하면, 체크되지않은 함수들은 재정의 되지 않기 때문에, 체크한 함수만 re rendering된다.