[react] react zustand persist store 구현하기

protomothis·2023년 1월 17일
0

React

목록 보기
2/2
post-thumbnail

시작하며

웹앱을 구현하다 보면 브라우저 내 저장소에 기록을 해야할 경우가 생긴다.
예를 들어서, 테이블 리스트를 오름차순으로 보여줄지 아니면 내림차순으로 보여줄지에
대한 단순 화면상의 편의 설정을 모두 서버에 저장할 수 없으니 이러한 설정 정보를 localstorage 등에 저장하는 것이다.

Zustand 내에서 persist state 구현을 지원한다

아래 예제에서는 다음과 같은 상황을 가정했다.
구매할 상품을 담는 장바구니 서비스의 전역 스토어를 만든다면,
유저가 장바구니에 물건을 담고 잠시 웹을 종료했다고 해서 이력이 소거되면 불편하지 않을까?
그래서 유저가 장바구니에 물건을 담거나 빼는 행위를 할때마다 장바구니 상태를 보존할 수 있도록 persist state 로 만들어보자.

export interface ICartStoreStates {
  // 상품 리스트
  cartList: ICart[];
}

export type ICartStorePersist = (config: StateCreator<ICartStore>, options: PersistOptions<ICartStoreStates>) => StateCreator<ICartStore>;

export interface ICartStoreActions {
  actions: {
    // 장바구니에 물건을 담거나, 빼거나 하는 action hook에 대한 모델 정의
    ...
  }
}

// 스토어 내 state 초기값에 대한 정의
const initialState: ICartStoreStates = {
  cartList: [],
};

export interface ICartStore extends ICartStoreStates, ICartStoreActions {}

const useCartStore = create<ICartStore>(
  (persist as ICartStorePersist)((set, get) => ({
    // region states
    cartList: initialState.cartList,
    // endregion

    // region actions
    actions: {
      ...
    }
    // endregion
  }), {
    name: 'cart-store', // localstorage 내 저장될 states 값을 관리하는 key
    // store 내 존재하는 모든 state 를 persist store 에 저장하지 않기 위해 partialize 옵션을 사용하여
    // 필요한 state 만 persist state 로 지정한다.                             
    partialize: (state) => ({ cartList: state.cartList }),
  }
));

nextJS 와 같은 SSR 환경에서는..?

// 
const dummyStorageApi = {
  getItem: () => null,
  setItem: () => undefined,
}

const useStore = create(
  persist(
    set => ({
      user: null,
      updateUser: user => set({ user }),
    }),
    {
      name: 'someStoragekey',
      // 실제 storage 를 체크하고 없으면 dummy storage 를 넘겨주자..
      storage: typeof window !== 'undefined' ? window.localStorage : dummyStorageApi,
    },
  ),
)

hooks 구현

// region hooks
export const useCartStoreState = <T extends keyof ICartStoreStates>(key: T) => {
  const [state, setState] = useState(initialState[key]);
  const zustandState = useCartStore((persistedState) => persistedState[key]);

  useEffect(() => {
    setState(zustandState);
  }, [zustandState]);

  return state;
}
export const useCartStoreActions = () => useCartStore((state) => state.actions);
// endregion
profile
frontend dev, home server lover.

0개의 댓글