Skip to content

Instantly share code, notes, and snippets.

@zoontek
Created February 12, 2023 14:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zoontek/841960ce516d16298e5934799d057f9f to your computer and use it in GitHub Desktop.
Save zoontek/841960ce516d16298e5934799d057f9f to your computer and use it in GitHub Desktop.
import { useSyncExternalStore } from "react";
export type Atom<Value> = {
get: () => Value;
set: (value: Value | ((prevValue: Value) => Value)) => void;
subscribe: (callback: (value: Value) => void) => () => void;
reset: () => void;
};
export const atom = <Value>(initialValue: Value): Atom<Value> => {
const callbacks = new Set<(value: Value) => void>();
let currentValue: Value = initialValue;
return {
get() {
return currentValue;
},
set(value) {
currentValue =
typeof value === "function"
? (value as (prevValue: Value) => Value)(currentValue)
: value;
callbacks.forEach((callback) => callback(currentValue));
},
subscribe(callback) {
callbacks.add(callback);
return () => {
callbacks.delete(callback);
};
},
reset() {
currentValue = initialValue;
callbacks.forEach((callback) => callback(currentValue));
},
};
};
export const useAtom = <Value>(atom: Atom<Value>): Value =>
useSyncExternalStore(atom.subscribe, atom.get, atom.get);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment