UNPKG

alistair

Version:
127 lines (124 loc) 4.69 kB
import { Dispatch, SetStateAction, DependencyList } from 'react'; interface Atom<out T, in out W> { /** * Gets a value from the atom * @returns The current value of the atom */ get: () => T; /** * The setter function for the atom */ set: Dispatch<W>; /** * Subscribes to the atom, and fires a callback when the atom changes * @param notify A callback that will be fired when the atom changes, passes the new value * @returns A function to unsubscribe from the atom */ subscribe: (notify: (value: T) => void) => () => void; } declare function atom<T>(initialValue?: T): Atom<T, SetStateAction<T>>; /** * Creates an atom with a writable interface. This is a more of an advanced API, and should only be reached for * if you need logic that is more complex than what `atom` provides. * @param init A value to initialize the atom with * @param toAction A function that takes the next value and returns the next state or a function that takes the previous state and returns the next state * @returns An atom with a writable interface * * @example * ```ts * function atomWithUpdatedAt<T>(initialValue: T) { * // First generic is the value when read, second is the value to be set * return writable<{value: T; updatedAt: number}, T>( * // Initial value: * {value: initialValue, updatedAt: Date.now()}, * * // Calculate the next state * next => ({value: next, updatedAt: Date.now()}), * ); * } * * const atom = atomWithUpdatedAt(0); * * atom.get(); // {value: 0, updatedAt: <timestamp>} * * ``` * * You can even take this a futher and write a reducer pattern, since the reducer has to return a `SetStateAction` (allowing you to access previous state). * * ```ts * type Action = {type: 'increment'} | {type: 'decrement'} | {type: 'set'; value: number}; * * function reducer(state: number, action: Action): number { * switch (action.type) { * case 'increment': * return state + 1; * case 'decrement': * return state - 1; * case 'set': * return action.value; * } * } * * // Must pass `<number, Action>` type arguments * const atom = writable<number, Action>(0, next => old => reducer(old, next)); * * atom.set({type: 'increment'}); * atom.get(); // 1 * * atom.set({type: 'set', value: 5}); * atom.get(); // 5 * * atom.set({type: 'decrement'}); * atom.get(); // 4 * ``` */ declare function writable<T, W = T>(init: T, toAction: (value: W) => SetStateAction<T>): Atom<T, W>; /** * Hook to get the current value of an atom * @param atom The atom to consume * @returns The current value of the atom */ declare function useAtomValue<T, W>(atom: Atom<T, W>): T; /** * Use the value of an atom * @param atom The atom to consume * @returns The current state of the atom, as well as a stable writer */ declare function useAtom<T, W>(atom: Atom<T, W>): [value: T, write: Dispatch<W>]; /** * Get immediately notified when an atom's value changes * @param atom The atom to listen to * @param callback A callback that will be fired when the atom changes. */ declare function useAtomDidChange<T, W>(atom: Atom<T, W>, callback: (value: T) => void): void; /** * Selects/computes a value from an atom, and re-renders the component when the selected value changes * * The selector function can be unstable, but the value it returns should be stable. This means you could do something like this * `const totalMessages = useSelectAtomValue(chatAtom, chat => chat.messages.length);` * * Or this is also okay, because you're not computing a new value, just selecting a value from the atom: * `const message = useSelectAtomValue(chatAtom, chat => chat.messages);` * * But NOT this, because we make a new array every time the selector is called (which will trigger a re-render): * `const totalMessages = useSelectAtomValue(chatAtom, chat => [...chat.messages, "hello"]);` * * If you need this kind of behaviour, you should use this in combination with `useMemo`: * * ```ts * const messages = useSelectAtomValue(chatAtom, chat => chat.messages); * const mappedMessages = useMemo(() => [...messages, "hello"], [messages]); * ``` * * @param atom The atom to select a value from-inherited from the atom * @param selector The selector function * @returns The selected value * * @example * ```ts * const messages = useSelectAtomValue(chatAtom, chat => chat.messages); * console.log('messages', messages); * ``` */ declare function useSelectAtomValue<T, W, U>(atom: Atom<T, W>, selector: (atom: T) => U, dependencies?: DependencyList): U; export { type Atom, atom, useAtom, useAtomDidChange, useAtomValue, useSelectAtomValue, writable };