Skip to content

Instantly share code, notes, and snippets.

@grocco
Created October 10, 2025 10:55
Show Gist options
  • Select an option

  • Save grocco/0c250b01a9c30520c606ba724add5cca to your computer and use it in GitHub Desktop.

Select an option

Save grocco/0c250b01a9c30520c606ba724add5cca to your computer and use it in GitHub Desktop.
Proxy-based state management for React 18+
import { useSyncExternalStore } from "react";
type Listener = () => void;
export function createStore<T extends object>(initialState: T) {
const listeners = new Set<Listener>();
let cachedSnapshot: T;
const notify = () => {
cachedSnapshot = clone(state);
listeners.forEach((fn) => fn());
};
const subscribe = (fn: Listener) => {
listeners.add(fn);
return () => listeners.delete(fn);
};
const clone = (obj: any): any =>
Array.isArray(obj)
? obj.map(clone)
: obj && typeof obj === "object"
? Object.fromEntries(Object.entries(obj).map(([k, v]) => [k, clone(v)]))
: obj;
const makeReactive = (obj: any): any => {
if (typeof obj !== "object" || obj === null) return obj;
return new Proxy(obj, {
get(target, prop, receiver) {
const value = Reflect.get(target, prop, receiver);
return typeof value === "object" && value !== null
? makeReactive(value)
: value;
},
set(target, prop, value, receiver) {
const oldValue = target[prop];
const didChange = oldValue !== value;
const result = Reflect.set(target, prop, value, receiver);
if (didChange) {
notify();
}
return result;
},
deleteProperty(target, prop) {
const result = Reflect.deleteProperty(target, prop);
notify();
return result;
},
});
};
const state = makeReactive(clone(initialState));
cachedSnapshot = clone(state); // init snapshot
const getSnapshot = () => cachedSnapshot;
function useStore<U>(
selector: (state: T) => U,
equalityFn: (a: U, b: U) => boolean = Object.is
): U {
let previous = selector(getSnapshot());
return useSyncExternalStore(
subscribe,
() => {
const next = selector(getSnapshot());
if (!equalityFn(previous, next)) {
previous = next;
}
return previous;
},
() => selector(getSnapshot())
);
}
return { store: state, useStore };
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment