-
useCallback카테고리 없음 2023. 5. 13. 23:48
주로 렌더링 성능을 최적화해야 하는 상황에서 사용된다. 이 Hook을 사용하면 이벤트 핸드럴 함수를 필요할 때만 생성할 수 있다.
컴포넌트의 렌더링이 자주 발생하거나 렌더링해야 할 컴포넌트의 개수가 많아지면 이 부분을 최적화해 주는 것이 좋다.
useCallback의 첫 번째 파라미터에는 생성하고 싶은 함수를 넣고, 두번째 파라미터에는 배열을 넣으면 된다. 이 배열에는 어떤 값이 바뀌었을때 함수를 새로 생성해야 하는지 명시해야 한다.
함수 내부에서 상태 값에 의존해야 할 떄는 그 값을 반드시 두번째 파라미터 안에 포함시켜 주어야 한다.
useCallback은 결국 useMemo로 함수를 반호나하는 상황에서 더 편하게 사용할 수 있는 Hool이다.
숫자, 문자열, 객체처럼 일반 값을 재사용 하려면 useMemo를 사용하고, 함수를 재사용하려면 useCallback을 사용한다.
const memoizedFunc = useCallback(func, deos) // 콜백함수, 의존성배열
useCallback은 의존성 배열에 담긴 값이 바뀌면 첫 번째 인수로 전달한 콜백 함수를 다시 만들어 반환한다. 만약 첫 번째 인수로 전달한 콜백 함수를 어떤 경우에도 다시 생성되지 않게 하려면 의존성 배열을 빈 배열로 전달하면 된다.
useCallback에서 전달한 콜백 함수에서 State변수에 접근하면 컴포넌트를 마운트할 때의 값, 즉 State의 초깃값이 반환된다.
이유는 콜백 한수가 컴포넌트의 마운트 시점 이후에는 다시 생성되지 않기 때문이다.
이렇듯 useCallback으로 래핑된 함수의 state의 변화를 추적하지 못하므로 자칫 의도치 않은 동작을 야기할 수 있다.
그렇다고 의존성 배열에 state변수를 전달하면, 결국 이를 업데이트할 때마다 함수를 계속 재생성하므로 useCallback을 적용한 의미가 사라진다.
이걸 해결하기 위해 함수형 업데이트 기능이 필요하다.
const callback = useCallback(() => { setState((state) => [newItem, ...state]); }, [])
setState에서 콜백 함수를 전달하면 함수형 업데이트를 사용할 수 있다.
이 함수는 항상 최신 state값을 매개변수로 저장한다.
즉, 콜백함수가 반환한 값은 새로운 state값이 되어 업데이트 된다.
최적화할 때 유의할 점
최적화는 항상 마지막에 한다.
최적화 이후에는 만든 기능을 수정하거나 확장하기 어렵다.
모든 것을 최적화할 필요는 없다.
아주 사소한 연산이나 리렌더까지 다 찾아내어 최적화를 하게되면 향후 서비스 확장이나 기능 수정을 어렵게 만들 수 있다.
컴포넌트 구조를 잘 설계햇는지 다시 한번 돌아보자.
하나의 컴포넌트에 많은 state를 생성하는 것은 매우 비효율적이며 최적화하기도 어렵다.