diff --git a/src/hooks.ts b/src/hooks.ts index a1b2f50..cd2398e 100644 --- a/src/hooks.ts +++ b/src/hooks.ts @@ -1,4 +1,4 @@ -import type { Atom, Selector } from './types.js'; +import type { Atom, AtomSelector } from './types.js'; import * as React from 'react'; @@ -19,7 +19,7 @@ import * as React from 'react'; * * @noinline */ -export const useAtomSelector = /*#__INLINE__*/(atom: Readonly>, selector: Selector) => { +export const useAtomSelector = (atom: Atom, selector: AtomSelector) => { const reselect = React.useRef(() => selector(atom.get())).current; return React.useSyncExternalStore( @@ -42,7 +42,7 @@ export const useAtomSelector = /*#__INLINE__*/(atom: Readonly>, se * * @nosideeffects */ -export const useAtomValue = /*#__INLINE__*/(atom: Readonly>) => { +export const useAtomValue = (atom: Atom) => { return React.useSyncExternalStore( atom.sub, atom.get, @@ -63,7 +63,7 @@ export const useAtomValue = /*#__INLINE__*/(atom: Readonly>) => { * * @nosideeffects */ -export const useSetAtomState = /*#__INLINE__*/(atom: Readonly>) => { +export const useSetAtomState = (atom: Atom) => { return React.useRef(atom.set).current; }; @@ -81,7 +81,7 @@ export const useSetAtomState = /*#__INLINE__*/(atom: Readonly>) => { * * @nosideeffects */ -export const useAtomState = /*#__INLINE__*/(atom: Readonly>) => { +export const useAtomState = (atom: Atom) => { const state = useAtomValue(atom); const update = useSetAtomState(atom); @@ -100,7 +100,7 @@ export const useAtomState = /*#__INLINE__*/(atom: Readonly>) => { * * @nosideeffects */ -export const useResetAtomState = /*#__INLINE__*/(atom: Readonly>) => { +export const useResetAtomState = (atom: Atom) => { return React.useRef(() => atom.set(atom.def)).current; }; @@ -117,8 +117,8 @@ export const useResetAtomState = /*#__INLINE__*/(atom: Readonly>) => * * @nosideeffects */ -export const useAtomConst = /*#__INLINE__*/(atom: Readonly>) => { - return React.useState(atom.get)[0]; +export const useAtomConst = (atom: Atom) => { + return React.useMemo(atom.get, []); }; /** @@ -134,6 +134,6 @@ export const useAtomConst = /*#__INLINE__*/(atom: Readonly>) => { * * @nosideeffects */ -export const useAtomSelectorConst = /*#__INLINE__*/(atom: Readonly>, selector: Selector) => { - return React.useState(() => selector(atom.get()))[0]; +export const useAtomSelectorConst = (atom: Atom, selector: AtomSelector) => { + return React.useMemo(() => selector(atom.get()), []); }; diff --git a/src/ssr.ts b/src/ssr.ts index acd78e6..a45a9d1 100644 --- a/src/ssr.ts +++ b/src/ssr.ts @@ -1,24 +1,24 @@ import type { Atom } from './types.js'; -import { store } from './store.js'; +import { unsafe_store } from './store.js'; /** * Sets the state of the passed atom. */ -export const hydrateAtom = (atom: Readonly>, value: Readonly) => { - store.set(atom.key, value); +export const hydrateAtom = (atom: Atom, value: T) => { + unsafe_store.set(atom.key, value); }; /** * Resets a state of passed atom. */ -export const resetAtom = (atom: Readonly>) => { - store.set(atom.key, atom.def); +export const resetAtom = (atom: Atom) => { + unsafe_store.set(atom.key, atom.def); }; /** * Resets states of passed atoms. */ -export const resetAtoms = (atoms: ReadonlyArray>>) => { - atoms.forEach(resetAtom); +export const resetAtoms = (atoms: ReadonlyArray>) => { + atoms.some(resetAtom); }; diff --git a/src/types.ts b/src/types.ts index 8703627..9d851a6 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,18 +1,32 @@ -export type Store = Map; +export type AtomKey = string | number | symbol; -export type AtomUpdater = (state: T) => T; -export type AtomValOrUpdater = T | AtomUpdater; +export type AtomStore = Map; +export type AtomStoreUpdate = Record; -export type Selector = (partial: T) => S; +export type AtomUpdater = (value: Value) => Update; +export type AtomValueUpdate = Update | AtomUpdater; -export type AtomGetter = () => T; -export type AtomSetter = (value: AtomValOrUpdater) => T; -export type AtomSubscribe = (set: (value: T) => void) => () => void; +export type AtomSelector = (value: Value) => Selected; -export type Atom = { - key: string; - def: T; - get: AtomGetter; - set: AtomSetter; - sub: AtomSubscribe; +export type AtomGetter = () => Value; +export type AtomSetter = (update: AtomValueUpdate) => Value; + +export type AtomSubscribe = (next: (value: Value) => void) => () => void; + +export type Atom = { + readonly key: AtomKey; + readonly def: Value; + + get: AtomGetter; + set: AtomSetter; + sub: AtomSubscribe; }; + +export type DynamicAtomGetter = ( + atom: Atom +) => Value; + +export type DynamicAtomSetter = ( + atom: Atom, + update: AtomValueUpdate +) => Value;