const fnTest = () => {
};
예시로 이런함수가 있다치면, 컴포넌트가 랜더링 될때마다 새로운 함수를 생성해서 쓰게됩니다.
이게 엄청난 부하가 생기는건 아니라고 하지만 그래도 재활용 할 수있으면 좋겠죠?
그때 쓰는게 useCallback입니다.
그 함수가 의존하는 값이 바뀌지 않는이상 기존의 함수를 계속 사용합니다.
const memoizedCallback = useCallback(() => x, [x]);
이런식으로 쓰게되면 x값이 변하지 않는 이상은 Virtual DOM 조차 리렌더링 하지않고 기존함수를 재사용한다는 얘기다.
하지만 이러한 특성때문에 남발하면 오히려 리렌더링만 더 불러서 오히려 성능상에 더 안좋은 결과를 낳을수도 있다.
어떤 경우에 오히려 성능하락을 낳을 수있는지 알아보자
const test1 = () => x;
const test2 = () => x;
// 여기서 test1 === test2 는 false
함수는 참조비교이기 때문에 두 함수의 메모리주소는 달라서 false를 반환한다.
useCallback은 뒤 의존성 배열의 값을 비교하여 리렌더링 할지말지를 결정함.
근데 여기에 객체를 넣으면 참조값을 비교하여서 이게 동일한지 아닌지 판단하기 때문에 이걸 잘 생각해야됨
함수 parameter, 컴포넌트 props 를 객체로 전달하는 경우
이때는 계속 리렌더링 될 것이다. 사용하는게 오히려 더 안좋다.
매번 새로운 참조를 전달해야하는 경우
새로운 참조면 계속 리렌더링이 된다. 애초에 사용 할이유가 없는 경우이다.
자식 컴포넌트의 랜더링의 불필요한 랜더링을 줄이기 위해서 memo와 함께 사용가능하다.
function Test () {
};
Test = React.memo(Test);
React.memo() 함수로 감싸주면 해당 컴포넌트 함수는 props 값이 변경되지 않는 한 다시 호출되지 않습니다.
근데 props로 함수를 넘겨주거나 하면, 역시나 참조값이 바껴서 계속 호출됨.
이 경우 그 넘겨주는 함수를 useCallback으로 설정해주면 항상 바뀌는 사태를 막을수있다.
역시나 뭔 기능있다고 무조건 남발하면 안좋다. 어떻게 동작하는지 알면 그래도 불상사를 막을수있다.