-
-
Save kyle-mccarthy/cae2df1089c71b9d6f5eb55992a15474 to your computer and use it in GitHub Desktop.
| import type { GetState, PartialState, SetState, State } from "zustand"; | |
| const noop = (..._: unknown[]): void => { | |
| /* noop */ | |
| }; | |
| export type Setter<T extends State> = ( | |
| s: Partial<T> | ((prev: T) => Partial<T>), | |
| replace?: boolean | |
| ) => void; | |
| export type Factory<T extends State> = (set: Setter<T>, get: () => T) => T; | |
| // Zustand recommnds splitting the store into separate "slices", but doesn't | |
| // really provide a great way to do this. [^slices] | |
| // | |
| // This allows for easily creating slices that are encapsulated as an object in | |
| // the primary store. `createSlice` does this by re-scoping the get and set | |
| // functions to the slice based on the property name passed as the first arg. | |
| // | |
| // # Example | |
| // | |
| // ## Create the slice for the primary store | |
| // ``` | |
| // interface UserSlice { | |
| // id?: number; | |
| // email?: string; | |
| // setId: (id: number) => void; | |
| // setEmail: (email: string) => void; | |
| // } | |
| // | |
| // const userFactory: Factory<AddressSlice> = (set, _get) => ({ | |
| // setId: (id: number) => set({ id }), | |
| // setEmail: (email: string) => set({ email }), | |
| // }); | |
| // | |
| // const createUserSlice = createSlice("user", userFactory); | |
| // ``` | |
| // | |
| // ## Create the store and include your slice | |
| // ``` | |
| // import { create } from "zustand"; | |
| // | |
| // interface Store { | |
| // user: UserSlice; | |
| // ... | |
| // } | |
| // | |
| // const store = create((set, get) => ({ | |
| // user: createUserSlice(set, get), | |
| // })); | |
| // ``` | |
| // | |
| // [^slices]: https://github.com/pmndrs/zustand/wiki/Splitting-the-store-into-separate-slices | |
| export const createSlice = < | |
| P extends keyof Z, | |
| S extends State, | |
| Z extends { [k in P]: S } | |
| >( | |
| property: P, | |
| factory: Factory<S> | |
| ): ((set: SetState<Z>, get: GetState<Z>) => S) => { | |
| return (set, get) => { | |
| const getter = (): S => { | |
| return get()[property]; | |
| }; | |
| const setter: Setter<S> = (arg, replace) => { | |
| const prev = get()[property]; | |
| const next = typeof arg === "function" ? arg(prev) : arg; | |
| if (next === prev) { | |
| return noop(); | |
| } | |
| if (replace) { | |
| return set({ [property]: next as S } as PartialState<Z>); | |
| } | |
| return set({ | |
| [property]: { | |
| ...prev, | |
| ...next, | |
| } as S, | |
| } as PartialState<Z>); | |
| }; | |
| return factory(setter, getter); | |
| }; | |
| }; |
I've tried using this and being new to Zustand I can't get it to work fully, as the 4 imports are all deprecated.
import { GetState, PartialState, SetState, State } from "zustand";
When I use it the 2nd one of the 2 below works, however as soon as I wrap immer, devtools or even persist around it (the first one), I get red squiggle lines. Would it be possible for you to update the above code to use the latest version of Zustand?
export const useStoreFactory = createSelectors(
create(
immer((set, get) => ({
user: createUserSlice(set, get),
userSettings: createUserSettingsSlice(set, get),
}))
)
);
export const useStoreFactoryWorks = createSelectors(
create((set, get) => ({
user: createUserSlice(set, get),
userSettings: createUserSettingsSlice(set, get),
}))
);
Zustand used to treat all state as an object. It looks like that changed recently.