리액트는 불필요한 렌더링을 하지 않고 성능을 최적화할 수 있는 여러 방법을 제공한다.
shouldComponentUpdate(nextProps, nextState) {
if (pros와 state의 변경 X) {
return false;
}
return true;
}
리액트의 라이프 사이클 메서드 중 하나이며, 클래스 컴포넌트의 업데이트 시점을 리액트에게 알려줌으로써 렌더링 성능을 향상시킬 수 있다.
일반적인 사용법은 컴포넌트의 prop와 state가 변경되었는지 확인하고, 변경되지 않았을 때 false를 리턴하는 것이다. true를 반환하면 render함수가 호출되고, false를 리턴하면 리렌더링되지 않는다.
class Greeting extends PureComponent {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}
PureComponent를 base clas로 구현하면 Component + shoudComponentUpdate를 사용하는 것과 같은 효과를 얻을 수 있다.
공식문서에서 클래스 컴포넌트보다는 함수 컴포넌트를 사용할 것을 권장하고 있으므로 참고만 하자.
const cachedValue = useMemo(calculateValue, dependencies)
useMemo는 메모이제이션된 ‘값’을 반환한다.
useMemo는 의존성이 변경되었을 때에만 메모이제이션된 값을 다시 계산한다.
따라서 컴포넌트가 리렌더링 되더라도 의존성이 변할때만 useMemo에 등록된 함수가 실행되므로 경우에 따라 불필요한 연산을 생략하여 성능 향상을 꾀할 수 있다.
const MemoizedComponent = memo(SomeComponent, arePropsEqual?)
React.memo는 컴포넌트 자체를 메모이제이션한다.
props가 바뀌지 않으면 컴포넌트 자체의 리렌더링을 건너뛴다.
동일한 props로 컴포넌트가 자주 리렌더링되는 경우에 유용하다.
const cachedFn = useCallback(fn, dependencies)
useCallback은 메모이제이션된 ‘함수’를 반환한다.
메모이제이션된 함수를 props로 받은 자식 컴포넌트를 memo로 감싸면 해당 컴포넌트의 불필요한 리렌더링을 건너뛸 수 있다.
리액트는 엘리먼트 혹은 컴포넌트의 변화를 감지하기 위한 고유한 값으로 key 속성을 사용한다. 고유한 key값은 리액트가 효율적으로 reconciliation하도록 돕는 역할을 한다.
reconciliation에서 DOM 노드의 자식들을 재귀적으로 처리할 때 리액트는 key를 통해 기존 트리와 이후 트리의 자식들이 일치하는지 확인한다.
또 key는 배열이 다시 렌더링 되는 과정에서 리스트 아이템의 순서를 보장할 수 있다.
key가 없으면 리스트의 모든 자식들을 순차적으로 비교하여 변화를 감지해야 한다.
즉 리액트는 key를 통해 변화가 감지된 부분만을 캐치하여 효율적으로 DOM을 업데이트할 수 있다.