useCallback()
은 함수를 메모이제이션(memoization)하기 위해서 사용되는 hook 함수다. 첫번째 인자로 넘어온 함수를, 두번째 인자로 넘어온 배열 내의 값이 변경될 때까지 저장해놓고 재사용할 수 있게 해준다.
useCallback은 2개의 인자를 받는다.
const memoizedCallback = useCallback(함수, 배열);
const memoizedCallback = useCallback(
() => {
// 실행할 로직
doSomething(a, b);
},
[a, b]
);
// a 또는 b가 바뀔 때만 새 함수 생성, 아니면 기존 함수 재사용
useCallback
을 활용한 자식 컴포넌트에 콜백 전달 최적화
import React, { useState, useCallback, memo } from 'react';
// callback이 바뀌지 않으면 리렌더링하지 않는 최적화된 자식 컴포넌트
const Button = memo(({ onClick, children }) => {
console.log('Button render:', children);
return <button onClick={onClick}>{children}</button>;
});
export default function Counter() {
const [count, setCount] = useState(0);
const [text, setText] = useState('');
// text가 바뀔 때만 함수가 재생성되고, count가 바뀔 때는 동일한 참조 유지
const increment = useCallback(() => {
setCount(c => c + 1);
}, []); // 의존성 비워두면 마운트 이후엔 한 번만 생성
// text가 바뀔 때만 다시 생성
const onChange = useCallback(e => {
setText(e.target.value);
}, []);
return (
<div>
<div>Count: {count}</div>
<Button onClick={increment}>Increment</Button>
<div>
<input value={text} onChange={onChange} placeholder="Type something" />
</div>
</div>
);
}
Counter
가 리렌더될 때마다 increment
함수도 새로 생성되어, props로 받은 Button
은 항상 새 함수 객체를 감지하고 리렌더됨.[]
)로 설정하면, increment
는 최초 마운트 시 한 번만 생성되고 이후는 같은 참조를 유지Button
은 onClick
참조가 바뀌지 않으므로, memo
에 의해 불필요한 리렌더링을 피함