react 스터디에서 리액트를 다루는 기술이라는 책을 선정했고 이 책을 읽고 배운 것을 바탕으로 작성되었다.
React Developer Tools
설치Profiler
탭 분석❗ 주로 업데이트가 발생한 컴포넌트랑 관계없는 컴포넌트들도 리렌더링 되는 문제 발생
컴포넌트는 다음과 같은 상황에서 리렌더링이 발생함
props
가 변경될 때state
가 바뀔 때forceUpdate
함수가 실행될 때❗ 불필요한 리렌더링이 발생하지 않도록 해야 한다.
life cycle method
중 shouldComponentUpdate
사용하면 된다.React.memo
라는 함수를 사용한다.props
가 바뀌지 않았다면 리렌더링하지 않도록 하여 컴포넌트의 리렌더링 성능을 최적화할 수 있다.export default React.memo(MyComponent);
useCallback
을 이용하여 특정 함수가 리렌더링마다 새로 생성되지 않고 재사용할 수 있도록 하지만, useCallback
과 더불어 useState
의 함수형 업데이트를 이용하여 함수 생성 횟수를 더욱 더 줄여 리렌더링 성능을 최적화할 수 있다.const [number, setNumber] = useState(0);
// Before: number 상태 값이 바뀔 때 마다 등록된 함수가 새로 생성됨.
const onIncrese = useCallback(
() => setState(number + 1);,
[number]
);
// After
const onIncrease = useCallback(
() => setState(prevNumber => prevNumber + 1);,
[]
);
setState
함수에 함수인자를 넣으면 그 함수는 이전 상태값을 인자로 받아 참조하여 상태값을 업데이트시킬 수 있다.useCallback
의 두번째 인자로 빈 배열을 넣어 초기렌더링 시에만 함수를 생성하고 리렌더링될 때마다 처음에 생성된 함수를 재사용하도록 한다.function reducer(state, action){
switch(action.type){
case "INCREMENT":
return { number : state.number + 1};
default:
return state;
}
}
...
const [state, dispatch] = useReducer(reducer, { number : 0 });
const onIncrese = useCallback(
dispatch({ type: "INCREMENT" });,
[]
);
useReducer
의 장점은 컴포넌트의 state
업데이트 로직을 바깥으로 빼낼 수 있다는 것이다.reducer
함수는 첫번째 인자로 항상 현재 상태값을 가져오기 때문에 컴포넌트 내부에서는 dispatch
함수를 이용하여 action
인자를 받아 reducer
함수를 호출하면 된다.useCallback
으로 등록된 함수 내부에서는 현재 상태값에 의존하지 않아도 되므로 두 번째 인자로 빈 배열을 전달하여 초기 렌더링 시 생성된 함수를 리렌더링될 때마다 재사용할 수 있도록 한다.react-virtualized
라이브러리를 이용하면 스크롤되기 전에 보이지 않는 컴포넌트는 렌더링하지 않고 크기만 차지하게끔 할 수 있다.useMemo
와 useCallback
은 주로 컴포넌트 성능을 최적화하기 위해 사용된다.trade-off
가 존재한다. 퍼포먼스를 최적화시켰지만, 컴퓨터 자원 등 소모되는 자원이 있다.useMemo
와 useCallback
을 이용하면 컴포넌트 성능을 최적화할 수 있지만 의존성 배열의 값을 관리하고 메모이제이션을 위해 메모리를 소모해야 한다. 어쩌면 이득보다 더 큰 대가를 치러야 할 수 있다.Referential Equality
책임감 있게 최적화해야 한다 ❗
적재적소에 사용하자 ❗