본문 바로가기

Front-End: Web

shallow로 zustand 최적화하기

반응형

Intro

최상단에 Home 컴포넌트가 있고, 하위로 다양한 컴포넌트가 있는 구조가 있다고 하자.

그럼 하위 컴포넌트에서 상태값이 바뀔 때마다 Home 컴포넌트도 리렌더링된다.

Home
 |-- Memo
 |-- Summary
 |-- Dialog
 ㄴ-- ...

 

이를 방지하고자 zustand에서는, shallow를 제공한다.

 

 

shallow

기본적으로 zustand는 엄격한 비교(old === new)로 변경사항을 감지한다.

그래서 state가 변경될 때마다 컴포넌트가 리렌더링된다.

const nuts = useBearStore((state) => state.nuts)
const honey = useBearStore((state) => state.honey)

만약 state가 하나의 객체에서 일부 state들을 한꺼번에 가져오고 싶을 때, zustand에게 shallow를 전달하여 얕은 비교를 하고 싶다고 알릴 수 있다.

그러면 모든 state가 바뀔 때마다가 아니라, 일부 선택한 state만 바뀔 때마다 리렌더링된다.

import { shallow } from 'zustand/shallow'

// Object pick, re-renders the component when either state.nuts or state.honey change
const { nuts, honey } = useBearStore(
  (state) => ({ nuts: state.nuts, honey: state.honey }),
  shallow
)

// Array pick, re-renders the component when either state.nuts or state.honey change
const [nuts, honey] = useBearStore(
  (state) => [state.nuts, state.honey],
  shallow
)

// Mapped picks, re-renders the component when state.treats changes in order, count or keys
const treats = useBearStore((state) => Object.keys(state.treats), shallow)

 

shallow.d.ts

export default function shallow<T, U>(objA: T, objB: U): boolean;

A, B를 비교하고, 바뀌었을 때 true를 반환해줌

 

 

import shallow from 'zustand/shallow';

const [action1, action2, action3] = store(state => [state.action1, state.action2, state.action3]);

shallow를 사용하면 action1, action2, action3이 바뀔 때에만 리렌더링이 된다.

하위 컴포넌트들에도 모두 shallow를 적용해주면 컴포넌트가 최적화된다.

 

zustand에서도 shallow를 사용하는 것을 권장한다.

 

여기서 더 나아가서 리렌더링을 제어하고 싶으면, custom equality function(compare)을 주자.

const treats = useBearStore(
  (state) => state.treats,
  (oldTreats, newTreats) => compare(oldTreats, newTreats)
)

 

 

 


참고 자료

GitHub - pmndrs/zustand: 🐻 Bear necessities for state management in React

반응형