zustand 잘쓰는법!

박정빈·2024년 7월 5일
`zustand`를 처음 사용해보며 알게된 것들을 기재합니다.

전역 상태로 list라는 이름의 Set을 만들고,
Setadd delete has함수를 실행시켜주는 action을 만들어서,
다른 파일에서 import해서 사용하고 싶었다.

import { create } from "zustand";
type storeState = {
  list: Set<string>;
};
type action = {
  pushList: (item: string) => void;
  findList: (item: string) => boolean;
  popList: (item: string) => void;
};
export const useStore = create<storeState & action>((set) => ({
  list: new Set(),
  pushList: (item) =>
    set((state) => {
      const tmpSet = new Set(state.list);
      tmpSet.add(item);
      return { list: tmpSet };
    }),
  findList: (item) => {
    const tmpState: storeState = useStore.getState();
    return tmpState.list.has(item);
  },
  popList: (item) =>
    set((state) => {
      const tmpSet = new Set(state.list);
      tmpSet.delete(item);
      return { list: tmpSet };
    }),
}));

이런 방식을 사용하면 하나의 값만 확인/사용하고 싶어도 store전체를 가져올 수 밖에 없다.

커스텀 훅만을 export해라

//...생략
//전체 store는 export하지 않아 전체 store를 사용하는 실수를 방지한다.
const useStore = create<storeState & action>((set) => ({
  list: new Set(),
  pushList: (item) =>
    set((state) => {
      const tmpSet = new Set(state.list);
      tmpSet.add(item);
      return { list: tmpSet };
    }),
  findList: (item) => {
    const tmpState: storeState = useStore.getState();
    return tmpState.list.has(item);
  },
  popList: (item) =>
    set((state) => {
      const tmpSet = new Set(state.list);
      tmpSet.delete(item);
      return { list: tmpSet };
    }),
}));
// state를 따로 export 해준다.
export const useList = () => useStore((state) => state.list);

이렇게 state를 따로 export하여 하나의 값만 가져올 수 있으며, 사용하지 않는 state가 변경되었을때 렌더링되는 등의 일을 방지할 수 있다.

list값을 변경해주는 action들은 export되지 않았는데 어떻게 사용하면 좋을까?

State에서 Action을 분리

action을 위한 namespace를 만들고, 그 namespaceexport 할 수 있다. action들은 상태가 아니고 정적이므로 따로 분리시켜서 사용하면 불필요한 렌더링이 되는 것을 막을 수 있다.

import { create } from "zustand";
type storeState = {
  list: Set<string>;
};
type action = {
  actions: {
    pushList: (item: string) => void;
    findList: (item: string) => boolean;
    popList: (item: string) => void;
  };
};
const useStore = create<storeState & action>((set) => ({
  list: new Set(),
  actions: {//action을 위한 namespace
    pushList: (item) =>
      set((state) => {
        const tmpSet = new Set(state.list);
        tmpSet.add(item);
        return { list: tmpSet };
      }),
    findList: (item) => {
      const tmpState: storeState = useStore.getState();
      return tmpState.list.has(item);
    },
    popList: (item) =>
      set((state) => {
        const tmpSet = new Set(state.list);
        tmpSet.delete(item);
        return { list: tmpSet };
      }),
  },
}));

export const useList = () => useStore((state) => state.list);
//action도 따로 export 해준다.
export const useActions = () => useStore((state) => state.actions); 

이렇게 해줌으로써 actions 또한 구조분해할당 문법을 통해서 따로 사용할 수 있다

const {findList} = useActions();

참조

0개의 댓글