-
-
Notifications
You must be signed in to change notification settings - Fork 709
Expand file tree
/
Copy pathuseAtom.ts
More file actions
100 lines (85 loc) · 2.43 KB
/
useAtom.ts
File metadata and controls
100 lines (85 loc) · 2.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import {
useCallback,
useContext,
useDebugValue,
useEffect,
useReducer,
} from 'react'
import type { Atom, Scope, SetAtom, WritableAtom } from './atom'
import { getScopeContext } from './contexts'
import { FLUSH_PENDING, READ_ATOM, SUBSCRIBE_ATOM, WRITE_ATOM } from './store'
const isWritable = <Value, Update>(
atom: Atom<Value> | WritableAtom<Value, Update>
): atom is WritableAtom<Value, Update> =>
!!(atom as WritableAtom<Value, Update>).write
export function useAtom<Value, Update>(
atom: WritableAtom<Value | Promise<Value>, Update>,
scope?: Scope
): [Value, SetAtom<Update>]
export function useAtom<Value, Update>(
atom: WritableAtom<Promise<Value>, Update>,
scope?: Scope
): [Value, SetAtom<Update>]
export function useAtom<Value, Update>(
atom: WritableAtom<Value, Update>,
scope?: Scope
): [Value, SetAtom<Update>]
export function useAtom<Value>(
atom: Atom<Value | Promise<Value>>,
scope?: Scope
): [Value, never]
export function useAtom<Value>(
atom: Atom<Promise<Value>>,
scope?: Scope
): [Value, never]
export function useAtom<Value>(atom: Atom<Value>, scope?: Scope): [Value, never]
export function useAtom<Value, Update>(
atom: Atom<Value> | WritableAtom<Value, Update>,
scope?: Scope
) {
if ('scope' in atom) {
console.warn(
'atom.scope is deprecated. Please do useAtom(atom, scope) instead.'
)
scope = (atom as { scope: Scope }).scope
}
const ScopeContext = getScopeContext(scope)
const [store] = useContext(ScopeContext)
const getAtomValue = useCallback(() => {
const atomState = store[READ_ATOM](atom)
if (atomState.e) {
throw atomState.e // read error
}
if (atomState.p) {
throw atomState.p // read promise
}
if (atomState.w) {
throw atomState.w // write promise
}
if ('v' in atomState) {
return atomState.v as Value
}
throw new Error('no atom value')
}, [store, atom])
const [value, forceUpdate] = useReducer(getAtomValue, undefined, getAtomValue)
useEffect(() => {
const unsubscribe = store[SUBSCRIBE_ATOM](atom, forceUpdate)
forceUpdate()
return unsubscribe
}, [store, atom])
useEffect(() => {
store[FLUSH_PENDING]()
})
const setAtom = useCallback(
(update: Update) => {
if (isWritable(atom)) {
store[WRITE_ATOM](atom, update)
} else {
throw new Error('not writable atom')
}
},
[store, atom]
)
useDebugValue(value)
return [value, setAtom]
}