Skip to content

Commit

Permalink
Fix server-side usage
Browse files Browse the repository at this point in the history
  • Loading branch information
eolme committed May 3, 2023
1 parent 130c448 commit e25e108
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 30 deletions.
20 changes: 10 additions & 10 deletions src/hooks.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Atom, Selector } from './types.js';
import type { Atom, AtomSelector } from './types.js';

import * as React from 'react';

Expand All @@ -19,7 +19,7 @@ import * as React from 'react';
*
* @noinline
*/
export const useAtomSelector = /*#__INLINE__*/<T, S>(atom: Readonly<Atom<T>>, selector: Selector<T, S>) => {
export const useAtomSelector = <T, S>(atom: Atom<T>, selector: AtomSelector<T, S>) => {
const reselect = React.useRef(() => selector(atom.get())).current;

return React.useSyncExternalStore(
Expand All @@ -42,7 +42,7 @@ export const useAtomSelector = /*#__INLINE__*/<T, S>(atom: Readonly<Atom<T>>, se
*
* @nosideeffects
*/
export const useAtomValue = /*#__INLINE__*/<T>(atom: Readonly<Atom<T>>) => {
export const useAtomValue = <T>(atom: Atom<T>) => {
return React.useSyncExternalStore(
atom.sub,
atom.get,
Expand All @@ -63,7 +63,7 @@ export const useAtomValue = /*#__INLINE__*/<T>(atom: Readonly<Atom<T>>) => {
*
* @nosideeffects
*/
export const useSetAtomState = /*#__INLINE__*/<T>(atom: Readonly<Atom<T>>) => {
export const useSetAtomState = <T>(atom: Atom<T>) => {
return React.useRef(atom.set).current;
};

Expand All @@ -81,7 +81,7 @@ export const useSetAtomState = /*#__INLINE__*/<T>(atom: Readonly<Atom<T>>) => {
*
* @nosideeffects
*/
export const useAtomState = /*#__INLINE__*/<T>(atom: Readonly<Atom<T>>) => {
export const useAtomState = <T>(atom: Atom<T>) => {
const state = useAtomValue(atom);
const update = useSetAtomState(atom);

Expand All @@ -100,7 +100,7 @@ export const useAtomState = /*#__INLINE__*/<T>(atom: Readonly<Atom<T>>) => {
*
* @nosideeffects
*/
export const useResetAtomState = /*#__INLINE__*/<T>(atom: Readonly<Atom<T>>) => {
export const useResetAtomState = <T>(atom: Atom<T>) => {
return React.useRef(() => atom.set(atom.def)).current;
};

Expand All @@ -117,8 +117,8 @@ export const useResetAtomState = /*#__INLINE__*/<T>(atom: Readonly<Atom<T>>) =>
*
* @nosideeffects
*/
export const useAtomConst = /*#__INLINE__*/<T>(atom: Readonly<Atom<T>>) => {
return React.useState(atom.get)[0];
export const useAtomConst = <T>(atom: Atom<T>) => {
return React.useMemo(atom.get, []);
};

/**
Expand All @@ -134,6 +134,6 @@ export const useAtomConst = /*#__INLINE__*/<T>(atom: Readonly<Atom<T>>) => {
*
* @nosideeffects
*/
export const useAtomSelectorConst = /*#__INLINE__*/<T, S>(atom: Readonly<Atom<T>>, selector: Selector<T, S>) => {
return React.useState(() => selector(atom.get()))[0];
export const useAtomSelectorConst = <T, S>(atom: Atom<T>, selector: AtomSelector<T, S>) => {
return React.useMemo(() => selector(atom.get()), []);
};
14 changes: 7 additions & 7 deletions src/ssr.ts
Original file line number Diff line number Diff line change
@@ -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 = <T>(atom: Readonly<Atom<T>>, value: Readonly<T>) => {
store.set(atom.key, value);
export const hydrateAtom = <T>(atom: Atom<T>, value: T) => {
unsafe_store.set(atom.key, value);
};

/**
* Resets a state of passed atom.
*/
export const resetAtom = <T>(atom: Readonly<Atom<T>>) => {
store.set(atom.key, atom.def);
export const resetAtom = <T>(atom: Atom<T>) => {
unsafe_store.set(atom.key, atom.def);
};

/**
* Resets states of passed atoms.
*/
export const resetAtoms = (atoms: ReadonlyArray<Readonly<Atom<any>>>) => {
atoms.forEach(resetAtom);
export const resetAtoms = (atoms: ReadonlyArray<Atom<any>>) => {
atoms.some(resetAtom);
};
40 changes: 27 additions & 13 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,32 @@
export type Store = Map<string, unknown>;
export type AtomKey = string | number | symbol;

export type AtomUpdater<T> = (state: T) => T;
export type AtomValOrUpdater<T> = T | AtomUpdater<T>;
export type AtomStore = Map<AtomKey, any>;
export type AtomStoreUpdate = Record<AtomKey, any>;

export type Selector<T, S> = (partial: T) => S;
export type AtomUpdater<Value, Update = Value> = (value: Value) => Update;
export type AtomValueUpdate<Value, Update = Value> = Update | AtomUpdater<Value, Update>;

export type AtomGetter<T> = () => T;
export type AtomSetter<T> = (value: AtomValOrUpdater<T>) => T;
export type AtomSubscribe<T> = (set: (value: T) => void) => () => void;
export type AtomSelector<Value, Selected> = (value: Value) => Selected;

export type Atom<T> = {
key: string;
def: T;
get: AtomGetter<T>;
set: AtomSetter<T>;
sub: AtomSubscribe<T>;
export type AtomGetter<Value> = () => Value;
export type AtomSetter<Value, Update = Value> = (update: AtomValueUpdate<Value, Update>) => Value;

export type AtomSubscribe<Value> = (next: (value: Value) => void) => () => void;

export type Atom<Value, Update = Value> = {
readonly key: AtomKey;
readonly def: Value;

get: AtomGetter<Value>;
set: AtomSetter<Value, Update>;
sub: AtomSubscribe<Value>;
};

export type DynamicAtomGetter = <Value, Update = Value>(
atom: Atom<Value, Update>
) => Value;

export type DynamicAtomSetter = <Value, Update = Value>(
atom: Atom<Value, Update>,
update: AtomValueUpdate<Value, Update>
) => Value;

0 comments on commit e25e108

Please sign in to comment.