
Next.js 환경에서 전역상태라이브러리 zustand를 사용하고 있었다.
전역 상태를 사용해야 하면서, 새로 고침 후에도 값이 남아 있도록 스토리지에 값을 저장해야했다.
localstorage hook을 만들어서 사용할 수도 있지만,
이왕 zustand를 쓰니, 이를 이용해서 스토리지에 저장하기로 하였다.
zustand의 공식 문서를 확인해보면,
Persist middleware을 이용해 state를 storage에 저장할 수 있다.
import { create } from 'zustand'
import { persist, createJSONStorage } from 'zustand/middleware'
export const useBearStore = create(
persist(
(set, get) => ({
bears: 0,
addABear: () => set({ bears: get().bears + 1 }),
}),
{
name: 'food-storage', // name of the item in the storage (must be unique)
storage: createJSONStorage(() => sessionStorage), // (optional) by default, 'localStorage' is used
}
)
)
const StorageKey = 'storage-key';
interface State {
state: boolean;
setState: (state: boolean) => void;
}
공식문서에 나와있는 예시는, javascript 문법으로 typescript의 타입은 알려주지 않았다.
기존에 zustand를 사용하는 방법에서는 (persist middleware 사용 x)
create 옆에 타입을 추가해서 시도해 보았더니 에러만 발생하였다..
에러메시지
'StateCreator<State, [], [["zustand/persist", State]]>' 형식의 인수는 'StateCreator<State, [], []>' 형식의 매개 변수에 할당될 수 없습니다.
'StateCreator<State, [], [["zustand/persist", State]]>' 형식은 '{ $$storeMutators?: [] | undefined; }' 형식에 할당할 수 없습니다.
'$$storeMutators' 속성의 형식이 호환되지 않습니다.
'[["zustand/persist", State]] | undefined' 형식은 '[] | undefined' 형식에 할당할 수 없습니다.
시도해 본 코드
import { create } from 'zustand';
import { persist } from 'zustand/middleware';
const useStateStore = create<State>(
persist(
(set) => ({
...
}),
{
name: StorageKey,
},
),
);
persist 의 옆에 persist<State>과 같이 타입을 추가하니, 의도한대로 타입을 지정하는데 성공하였다!
import { create } from 'zustand';
import { persist } from 'zustand/middleware';
const useStateStore = create(
persist<State>(
(set) => ({
state: false,
setState: (state: boolean) => {
set({ state });
},
}),
{
name: StorageKey,
},
),
);
이 글을 처음 쓸 당시에는 persist 옆에 타입을 추가했어야했는데, 최근에 다시 시도해보니 create 옆에 타입을 추가하는 방식으로 바뀐것을 확인했습니다.
따라서 밑과 같이 사용하면 됩니다!
interface State {
bears: number;
addABear: () => void;
}
export const useBearStore = create<State>(
persist(
(set, get) => ({
bears: 0,
addABear: () => set({ bears: get().bears + 1 }),
}),
{
name: StorageKey
}
)
);
기존에 사용하던 방식대로 state와 action을 분리한 훅을 생성해서, store을 사용하였다.
코드
export const useBooleanState = () =>
useRecommendCategoryStore((state) => state.state);
export const useBooleanStateAction = () =>
useRecommendCategoryStore((state) => state.setState);
state와 action을 분리한 훅을 사용하면
import { create } from 'zustand';
import { persist } from 'zustand/middleware';
const StorageKey = 'storage-key';
interface State {
state: boolean;
setState: (state: boolean) => void;
}
const useStateStore = create(
persist<State>(
(set) => ({
state: false,
setState: (state: boolean) => {
set({ state });
},
}),
{
name: StorageKey,
},
),
);
export const useBooleanState = () =>
useRecommendCategoryStore((state) => state.state);
export const useBooleanStateAction = () =>
useRecommendCategoryStore((state) => state.setState);
zustand persist를 이용해 storage에 값을 저장한다면,
기본적으로 local storage에 값이 저장되게 된다.
만약 session storage에 저장을 원한다면, storage를 임의로 지정해주어야한다.
const useStateStore = create(
persist<State>(
(set) => ({
state: false,
setState: (state: boolean) => {
set({ state });
},
}),
{
name: StorageKey,
storage: createJSONStorage(() => sessionStorage), // (optional) by default, 'localStorage' is used
},
),
);