가장 큰 차이점은
useMemo()
는 함수가 return하는 값을 저장하는 것이고
useCallback()
은 함수 그 자체를 저장하는 것이다.
useCallback
은 컴포넌트가 재평가가 될 때 함수를 다시 선언하지 않고 리액트 메모리 내부에 저장되어 있는 함수를 다시 사용한다.
사용 예)
const toggleParagraphHandler = useCallback(() => {
setShowParagraph((prevShowParagraph) => !prevShowParagraph);
}, []);
디펜던시(대괄호)에는 함수 내부에 있는 state
, props
, context
가 들어가면 된다. 하지만 setState
함수는 들어갈 필요가 없다. 리액트에서 항상 같은 함수가 되도록 보장해준다.
이유는 리액트에서는 함수 내부에서 state가 사용될 수 있기 때문이다.
JavaScript에서 Function은 Closure다. 즉 함수가 정의 될때 자바스크립트는 함수 내부의 모든 변수를 lock해버린다.
const toggleParagraphHandler = useCallback(() => {
if (allowToggle) {
setShowParagraph((prevShowParagraph) => !prevShowParagraph);
}
}, [allowToggle]);
위 코드에서 문제는 useCallback
과 함께 사용하게 되면 React는 메모리에 함수를 저장하게 되고 App.js가 재실행이 되던 말던 항상 같은 함수를 사용한다. (다시 생성해주지 않음)
allowToggle
은 바뀌었지만 useCallback
때문에 리액트 메모리에는 이전의 함수가 저장되어 있다.
그렇기 때문에 디펜던시에 allowToggle
을 추가해줌으로써 문제를 해결할 수 있다.
allowToggle
이 변경이 되면 함수를 다시 생성해주기 때문에 문제가 해결된다.