Skip to content

Instantly share code, notes, and snippets.

@syntax-punk
Created December 6, 2023 15:04
Show Gist options
  • Select an option

  • Save syntax-punk/7edaa96ea20ea634babd90f55568f8f7 to your computer and use it in GitHub Desktop.

Select an option

Save syntax-punk/7edaa96ea20ea634babd90f55568f8f7 to your computer and use it in GitHub Desktop.
"mini store" - a ridiculously simple global store implementation
export type ActionFunction<T> = (prev: T) => T;
export type Store<T> = {
getState: () => T;
setState: (action: T | ActionFunction<T>) => void;
subscribe: (callback: VoidFunction) => VoidFunction;
};
export const createStore = <T extends unknown>(initialState: T): Store<T> => {
let state = initialState;
const callbacks = new Set<() => void>();
const getState = () => state;
const setState = (nextState: T | ActionFunction<T>) => {
state =
typeof nextState === "function"
? (nextState as ActionFunction<T>)(state)
: nextState;
callbacks.forEach((callback) => callback());
};
const subscribe = (callback: () => void) => {
callbacks.add(callback);
return () => {
callbacks.delete(callback);
};
};
return { getState, setState, subscribe };
};
import { ActionFunction, createStore } from "./ministore";
import { useStore } from "./useStore";
let store = createStore({ count: 0 });
export function ComponentA() {
const [state, setState] = useStore(store);
const inc = () => {
setState((prev) => ({
...prev,
count: prev.count + 1,
}));
};
return (
<div>
<h1>Component - A</h1>
<h1>{state.count}</h1>
<button onClick={inc}>+1</button>
</div>
);
}
export const ComponentB = () => {
const [state, setState] = useStore(store);
const inc2 = () => {
setState((prev) => ({
...prev,
count: prev.count + 2,
}));
};
return (
<div>
<h1>Component - B</h1>
<h1>{state.count}</h1>
<button onClick={inc2}>+2</button>
</div>
);
};
import { useEffect, useState } from "react"
import { Store } from "./ministore";
export const useStore = <T extends unknown>(store: Store<T>) => {
const [state, setState] = useState(store.getState());
useEffect(() => {
const unsubscribe = store.subscribe(() => {
setState(store.getState());
});
setState(store.getState());
return unsubscribe;
}, [store]);
return [state, store.setState] as const;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment