🏆
Zustand Slice PatternのついったーPollやってます
どれが一番好みですか?全てTypeScriptサポートしてます。
Bare (Bear) Zustand
import { create, StateCreator } from "zustand";
interface CountSlice {
count: number;
incCount: () => void;
resetCount: () => void;
}
interface TextSlice {
text: string;
updateText: (newText: string) => void;
resetText: () => void;
}
interface SharedSlice {
reset: () => void;
}
const createCountSlice: StateCreator<CountSlice, [], [], CountSlice> = (
set,
) => ({
count: 0,
incCount: () => set((state) => ({ count: state.count + 1 })),
resetCount: () => set({ count: 0 }),
});
const createTextSlice: StateCreator<TextSlice, [], [], TextSlice> = (set) => ({
text: "Hello",
updateText: (text) => set({ text }),
resetText: () => set({ text: "Hello" }),
});
const createSharedSlice: StateCreator<
CountSlice & TextSlice,
[],
[],
SharedSlice
> = (set, get) => ({
reset: () => {
get().resetCount();
get().resetText();
},
});
const useCounterStore = create<CountSlice & TextSlice & SharedSlice>()(
(...a) => ({
...createCountSlice(...a),
...createTextSlice(...a),
...createSharedSlice(...a),
}),
);
Zustand Lens
import { create } from "zustand";
import { withLenses, lens } from "@dhmk/zustand-lens";
interface CountSlice {
value: number;
inc: () => void;
reset: () => void;
}
interface TextSlice {
value: string;
update: (newText: string) => void;
reset: () => void;
}
const countSlice = lens<CountSlice>((set) => ({
value: 0,
inc: () => set((prev) => ({ value: prev.value + 1 })),
reset: () => set({ value: 0 }),
}));
const textSlice = lens<TextSlice>((set) => ({
value: "Hello",
update: (newText) => set({ value: newText }),
reset: () => set({ value: "Hello" }),
}));
const useCounterStore = create<{
count: CountSlice;
text: TextSlice;
reset: () => void;
}>(
withLenses((set, get) => ({
count: countSlice,
text: textSlice,
reset: () => {
get().count.reset();
get().text.reset();
},
})),
);
Zustand Slices
import { create } from "zustand";
import { createSlice, withSlices } from "zustand-slices";
const countSlice = createSlice({
name: "count",
value: 0,
actions: {
incCount: () => (prev) => prev + 1,
reset: () => () => 0,
},
});
const textSlice = createSlice({
name: "text",
value: "Hello",
actions: {
updateText: (newText: string) => () => newText,
reset: () => () => "Hello",
},
});
const useCounterStore = create(withSlices(countSlice, textSlice));
Zustand Valtio
import { create } from "zustand";
import { withProxy } from "zustand-valtio";
const countSlice = {
value: 0,
inc() {
this.value++;
},
reset() {
this.value = 0;
},
};
const textSlice = {
value: "Hello",
update(newText: string) {
this.value = newText;
},
reset() {
this.value = "Hello";
},
};
const useCounterState = create(
withProxy({
count: countSlice,
text: textSlice,
reset() {
this.count.reset();
this.text.reset();
},
}),
);
TypeScript Playgroundのリンクはこちらか
Zustand Valtioについて補足
Zustand Valtioはまさに昨日完成したもので、想像以上に面白いものに仕上がりました。
元々は、immerの代わりに使えないかなぁ、と思って始めたプロジェクトなのですが、これはかなり使い物になるんじゃないでしょうか。個人的には、this
は避けるのが基本スタンスなのですが、Valtioの場合はthis
の相性が良い(というか、それ以外だとうまくいかない)ので、活用する気になってます。
Discussion