듀오링고
스픽
수영 1시간
코딩테스트 준비
dfs 문제 풀기 - word search 20분
bfs 문제 풀기 - number of islands 7분
react advanced 10장
면접 스터디 준비
블로그 글쓰기
lang chain 책 읽기
•
문제 상황: heavy component에서 props로 onClick같은 콜백 함수를 넘겨야하고, 그 함수가 state를 참조하는 경우 매번 리렌더링이 일어난다.
•
해결 시도 및 실패: 이를 해결하기 위해 헤비컴포넌트를 React.memo로 메모이제이션하고 props에 useCallback을 사용해도, onClick에서 매 키 스트로크마다 달라지는 input 값을 참조한다면(그리고 dependencies에 명시가 되어있다면) onClick은 재생성되고 결국 memo는 props가 달라졌다고 판단해 헤비컴포넌트를 리렌더링한다.
const cache = {};
let prevValue;
const something = (value) => {
// check whether the value has changed
if (!cache.current || value !== prevValue) {
cache.current = () => { console.log(value);
}; }
// refresh it
prevValue = value;
return cache.current;
};
JavaScript
복사
•
해결 시도 및 실패2: 그래서 이번에는 React.memo에서 comparison 콜백에서 헤비 컴포넌트의 title props가 달라졌을 때만 리렌더링이 되게 시도하지만, 이런 경우 title이 달라지지 않는 이상 onClick props는 이전 버전의 onClick함수를 캡처하고 있어서 만약에 input 값이 달라진다해도 헤비컴포넌트의 onClick 함수에서는 이전 input값을 계속해서 렌더링한다. 그렇다고 onClick을 comparison 로직에 추가한다면 React.memo(HeavyComponent)라는 기본 보일러플레이트 코드와 다를 바가 없다.
•
마지막 해결 시도 및 성공: 그래서 해결 방법은 ref를 사용하는 것이다. ref는 react의 리렌더링 사이클과는 무관하게 current 값을 보존한다. 그래서 ref.current를 호출하는 로직을 useCallback으로 감싸고 useCallback의 dependencies를 비워둔 채 onClick props에 전달하면 onClick props는 parent 컴포넌트가 리렌더링되어도 이전 함수와 같다고 판별될 것이다. 한편, ref.current 함수 내부에서 사용할 state 값을 업데이트하려면 useEffect를 통해 매 리렌더링마다 ref.current 함수를 재생성하여 state 값을 갱신해준다. useCallback에서는 클로저를 통해 ref 값에 접근하고, useEffect는 클로저를 통해 ref 값을 업데이트한다. 한편, 헤비컴포넌트는 useCallback을 통해 캐싱된 함수를 그대로 유지하면서 ref.current 내부에서는 클로저를 통해 갱신된 state에 접근할 수 있으니 메모이제이션도 하면서 갱신된 값을 로직에 사용할 수 있다는 장점이 있다.