시작하기전!
React의 함수형 컴포넌트는 렌더가 될때마다 내부 변수, 함수등이 초기화가 된다. ➪ 측 참조형 값들은 새로운 주소값이 할당되게 된다.
렌더링 전후 함수가 변경된 사항이 없음에도, 초기화되는 동작은 비효율 적이다.
하지만 함수형 컴포넌트도 함수이기 때문에 발생하는 어쩔수 없는 문제이기도 하다.
이를 해결하기 위해 useCallback
을 사용해 함수를 memoization 해보자!
const UseCallbackTest = () => {
const [currentTime, setCurrentTime] = useState('');
const showCurrentTime = () => {
const currentTime = new Date().toTimeString();
setCurrentTime(currentTime);
};
useEffect(() => {
console.log('useEffect 실행');
}, [showCurrentTime]);
return (
<Container>
<p>
<span>Time :</span> {currentTime}
</p>
<button onClick={showCurrentTime}>ClickCurrentTime</button>
<h3>code 비교</h3>
<pre>
<code>
{`const showCurrentTime = () => {
const currentTime =
new Date().toTimeString();
setCurrentTime(currentTime);
}`}
</code>
</pre>
</Container>
);
};
useCallback을 사용하지 않은
showCurrentTime
함수가 실행 될 때마다, 이 함수를 의존서 배열로 갖고 있는useEffect
가 실행 됨을 확인 할 수 있다. 이 현상은setCurrentTime
이 실행되며 리렌더가 일어나고showCurrentTime
함수가 초기화되며 주소값이 변경되기 때문에 발생한다.
const UseCallbackTest = (props: propsType) => {
const [currentTime, setCurrentTime] = useState('');
const showCurrentTimeCallback = useCallback(() => {
const currentTime = new Date().toDateString();
setCurrentTime(currentTime);
}, []);
useEffect(() => {
console.log('useEffect 실행');
}, [showCurrentTimeCallback]);
return (
<Container>
<p>
<span>Time :</span> {currentTime}
</p>
<button onClick={showCurrentTime}>ClickCurrentTime</button>
<h3>code 비교</h3>
<pre>
<code>
{`const showCurrentTimeCallback =
useCallback(() => {
const currentTime =
new Date().toDateString();
setCurrentTime(currentTime);
}, [])`}
</code>
</pre>
</Container>
);
};
이번에는
ClickCurrentTiem
버튼을 눌러도useEffect
가 실행 되지 않는 것을 확인 할 수 있다.showCurrentTimeCallback
함수는useCallback
을 사용하여 memoization 해 두었기 때문에 컴포넌트가 렌더링되더라도 함수는 초기화되지 않고 필요시 캐싱되있는 함수를 사용할 수 있게 된다. 이로인해 처음 선언된 함수의 주소값은useCallback
의 의존성 배열에 있는 인자의 변화가 감지되게 전까지 변경되지 않는다.