시작하기전!
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의 의존성 배열에 있는 인자의 변화가 감지되게 전까지 변경되지 않는다.