A Zustand-style factory creates one external state snapshot, lets an initializer define actions with set and get, and returns a React hook carrying the same vanilla store API. Implement createZustandStore(initializer) without a Provider. This question focuses on initialization, mutation semantics, subscriptions, and the callable-hook API—not selector equality optimization.
type SetState<S> = (
partial: Partial<S> | S | ((current: S) => Partial<S> | S),
replace?: boolean,
) => void;
function createZustandStore<S extends object>(
initializer: (set: SetState<S>, get: () => S) => S,
): {
<T = S>(selector?: (state: S) => T): T;
getState(): S;
setState: SetState<S>;
subscribe(listener: (next: S, previous: S) => void): () => void;
};
The initializer returns data and stable actions that close over set and get:
const useCounter = createZustandStore((set, get) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 })),
double: () => set({ count: get().count * 2 }),
}));
useCounter.getState().increment();
useCounter.getState().double();
useCounter.getState().count; // 2
Components select values from the same provider-free store:
function Count() {
const count = useCounter((state) => state.count);
return React.createElement('output', null, count);
}
useCounter.setState({ count: 7 }); // mounted readers update
initializer(setState, getState). It must return a non-null state object.replace=false, require a non-null object and shallow-merge it into the current snapshot. With replace=true, use the resolved value exactly.Object.is the current snapshot, do nothing. Otherwise update first, then notify a snapshot copy of listeners with (nextState, previousState).subscribe(listener) returns an unsubscribe function that removes that exact listener and remains safe when called repeatedly.getState, setState, and subscribe properties. Store state outlives every component and each factory call creates an independent store.useSyncExternalStore reads the whole snapshot. This minimal version wakes on every snapshot change, even when the selected result is equal.The full solution is part of Premium
Walkthrough, edge cases, complexity notes, and the runnable editor unlock with a Premium subscription.
Submissions are part of Premium
Unlock community code, comments, reactions, and framework-specific approaches.
A Zustand-style factory creates one external state snapshot, lets an initializer define actions with set and get, and returns a React hook carrying the same vanilla store API. Implement createZustandStore(initializer) without a Provider. This question focuses on initialization, mutation semantics, subscriptions, and the callable-hook API—not selector equality optimization.
type SetState<S> = (
partial: Partial<S> | S | ((current: S) => Partial<S> | S),
replace?: boolean,
) => void;
function createZustandStore<S extends object>(
initializer: (set: SetState<S>, get: () => S) => S,
): {
<T = S>(selector?: (state: S) => T): T;
getState(): S;
setState: SetState<S>;
subscribe(listener: (next: S, previous: S) => void): () => void;
};
The initializer returns data and stable actions that close over set and get:
const useCounter = createZustandStore((set, get) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 })),
double: () => set({ count: get().count * 2 }),
}));
useCounter.getState().increment();
useCounter.getState().double();
useCounter.getState().count; // 2
Components select values from the same provider-free store:
function Count() {
const count = useCounter((state) => state.count);
return React.createElement('output', null, count);
}
useCounter.setState({ count: 7 }); // mounted readers update
initializer(setState, getState). It must return a non-null state object.replace=false, require a non-null object and shallow-merge it into the current snapshot. With replace=true, use the resolved value exactly.Object.is the current snapshot, do nothing. Otherwise update first, then notify a snapshot copy of listeners with (nextState, previousState).subscribe(listener) returns an unsubscribe function that removes that exact listener and remains safe when called repeatedly.getState, setState, and subscribe properties. Store state outlives every component and each factory call creates an independent store.useSyncExternalStore reads the whole snapshot. This minimal version wakes on every snapshot change, even when the selected result is equal.The full solution is part of Premium
Walkthrough, edge cases, complexity notes, and the runnable editor unlock with a Premium subscription.
Submissions are part of Premium
Unlock community code, comments, reactions, and framework-specific approaches.
Unlock the solution & editor
Runnable editor + tests
Solve in the browser with instant Jest feedback.
Detailed solutions
Walkthroughs, edge cases, and complexity notes.
Multi-framework variants
React, Vue, Vanilla, Angular — same question, different stacks.