概要
Qiita初投稿です。
Reactのzustandで個人的によく使うmiddlewareである
- devtools
- immer
- persist
を毎回記述するのが面倒だったのと
Chrome拡張機能であるReduxDevToolsでzustandのstoreを見てみると
Action名が anonymous になり、以下のディスカッションでset時にAction名を指定できるとなっているがそれも面倒...ということでAction名の設定と上記middlewareをラップした関数を作成してみました。
https://github.com/pmndrs/zustand/discussions/1668
環境
CodeSandBoxで作成してみました。
依存関係などはそちらをご覧ください。
https://codesandbox.io/p/devbox/zustand-wrapper-r8vvnv?file=%2Fsrc%2Fstore-wrapper.ts%3A76%2C26
ソース
CodeSandBoxの「/src/store-wrapper.ts」ファイルが作成した関数です。
createStoreとcreatePersistStoreの2つの関数を定義しています。
immerを使用していて、WritableDraftで値をsetするときには関数になるので、functionであればfunctionの内容をそのままAction名にしています。
import { create, type StateCreator } from "zustand";
import { PersistOptions } from "zustand/middleware";
import { persist } from "zustand/middleware";
import { devtools } from "zustand/middleware";
import { immer } from "zustand/middleware/immer";
export const createStore = <T extends object>(
stateCreator: StateCreator<
T,
[["zustand/immer", never], ["zustand/devtools", never]],
[]
>,
name?: string,
) => {
if (import.meta.env.DEV) {
return create<T, [["zustand/devtools", never], ["zustand/immer", never]]>(
devtools<T, [], [["zustand/immer", never]]>(
immer<T, [["zustand/devtools", never]], []>((set, ...other) =>
stateCreator(
(args, rep) => {
let actName = "";
if (typeof args === "function") {
actName = args.toString();
} else {
actName = `set ${Object.keys(args).join(", ")}`;
}
return set(args, rep, actName);
},
...other,
),
),
{
name: name,
},
),
);
} else {
return create<T, [["zustand/immer", never]]>(
immer<T, [], []>((...prop) => stateCreator(...prop)),
);
}
};
export const createPersistStore = <T extends object>(
stateCreator: StateCreator<
T,
[
['zustand/devtools', never],
['zustand/persist', unknown],
['zustand/immer', never]
],
[]
>,
opt: PersistOptions<T, unknown>
) => {
if (import.meta.env.DEV) {
return create<
T,
[
['zustand/devtools', never],
['zustand/persist', unknown],
['zustand/immer', never]
]
>(
devtools<T, [], [['zustand/persist', unknown], ['zustand/immer', never]]>(
persist<
T,
[['zustand/devtools', never]],
[['zustand/immer', never]],
unknown
>(
immer<
T,
[['zustand/devtools', never], ['zustand/persist', unknown]],
[]
>((set, ...other) =>
stateCreator((args, rep) => {
let actName = ''
if (typeof args === 'function') {
actName = args.toString()
} else {
actName = `set ${Object.keys(args).join(', ')}`
}
return set(args, rep, actName)
}, ...other)
),
opt
),
{
name: opt.name
}
)
)
} else {
return create<T, [['zustand/persist', unknown], ['zustand/immer', never]]>(
persist(
immer<T, [['zustand/persist', unknown]], []>((...props) =>
stateCreator(...props)
),
opt
)
)
}
}
まとめ
上記のようなソースコードを色々探してみたのですが、なかなか見つからなかったので自作してみました。
同じような悩みを抱えている方の参考になれば幸いです。
ここをこうしたらもっと良くなるよ!など、アドバイスがあれば教えてください。