[승미님]

[참고할 자료들]
도서 리액트를 다루는 기술

useCallback이란

useCallback은 useMemo와 상당히 비슷한 함수이다. 주로 렌더링 성능을 최적화해야 하는 상황에서 사용하는데 이 Hook을 사용하면 만들어 놨던 함수를 재사용할 수 있다. 함수형 컴포넌트는 리렌더링될 때마다 새로 만들어진 함수를 사용하게 되는데, 대부분의 경우 이러한 방식은 문제가 없지만, 컴포넌트의 렌더링이 자주 발생하거나 렌더링해야 할 컴포넌트의 개수가 많아지면 이 부분을 최적화해 주는 것이 좋습니다.
(by. 리액트를 다루는 기술)
const memoizedCallback = useCallback( () => { doSomething(a, b); }, [a, b], );
공식문서 예제
메모이제이션된 콜백을 반환합니다.
인라인 콜백과 그것의 의존성 값의 배열을 전달하세요. useCallback은 콜백의 메모이제이션된 버전을 반환할 것입니다. 그 메모이제이션된 버전은 콜백의 의존성이 변경되었을 때에만 변경됩니다. 이것은, 불필요한 렌더링을 방지하기 위해 (예로 shouldComponentUpdate 를 사용하여) 참조의 동일성에 의존적인 최적화된 자식 컴포넌트에 콜백을 전달할 때 유용합니다. → 말이 굉장히 어렵다..
메모이제이션(memoization) (위키피디아) 동일한 계산을 반복해야 할 때, 이전에 계산한 값을 메모리에 저장함으로써 동일한 계산의 반복 수행을 제거하여 프로그램 실행 속도를 빠르게 하는 기술
  • 함수 객체는 "일반" 객체와 동일한 비교 원칙을 따른다. 함수 객체는 오직 자신에게만 동일하다. 함수의 동등성이란 함정 때문에, 메모이제이션을 적용할 때는 콜백을 받는 컴퍼넌트 관리에 주의해야한다. 리렌더를 할 때 마다 부모 함수가 다른 콜백 함수의 인스턴스를 넘길 가능성이 있다. 동일한 username 값이 전달되더라고, MemoizedLogout은 새로운 onLogout 콜백 때문에 리렌더링을 하게 된다. 메모이제이션이 중단되게 되는 것이다.이 문제를 해결하려면 onLogout prop의 값을 매번 동일한 콜백 인스턴스로 설정해야만 한다. useCallback()을 이용해서 콜백 인스턴스를 보존하면, useCallback() 함수는 항상 같은 함수 인스턴스를 반환하고, 리렌더링을 막을 수 있다. (토스 UI)
  • useCallback 문제점(?) (참고) → 구글에 문제점 키워드도 연관으로 나와서 추가
    • useCallback에서 자주 변경되는 값을 읽는 방법?
      • 주의
        props의 개별 콜백보다는 context에서 dispatch를 전달하는 것이 좋습니다. 아래 접근 방식은 완전성과 탈출구로만 여기에서 언급됩니다.
        드물게 useCallback을 사용하여 콜백을 메모해야 할 수도 있지만, 내부 함수 컴포넌트를 너무 자주 다시 만들어야 하므로 메모가 제대로 작동하지 않습니다. 메모하는 함수 컴포넌트가 이벤트 핸들러이고 렌더링 중에 사용되지 않는 경우 ref를 인스턴스 변수로사용하고 마지막으로 커밋 된 값을 수동으로 저장할 수 있습니다.
       
    • 콜백 전달을 피하는 법?
      • 우리는 대부분의 사람이 모든 레벨의 컴포넌트 트리를 통해 콜백을 수동으로 전달하는 것을 좋아하지 않는다는 것을 발견했습니다. 더 명백하지만 마치 “배관”이 많은 것처럼 느껴질 수 있습니다.
        큰 컴포넌트 트리에서 권장되는 대안은 context를 통해 useReducer에서 
        dispatch 함수 컴포넌트를 전달하는 것입니다.