-
-
Notifications
You must be signed in to change notification settings - Fork 567
/
Provider.ts
75 lines (71 loc) 路 2.22 KB
/
Provider.ts
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
import { createElement, useEffect, useRef, useState } from 'react'
import type { PropsWithChildren } from 'react'
import type { Atom, Scope } from './atom'
import { createScopeContainer, getScopeContext } from './contexts'
import type { ScopeContainer } from './contexts'
import { COMMIT_ATOM, createStoreForExport } from './store'
import type { VersionObject } from './store'
import { useDebugState } from './useDebugState'
export const Provider = ({
children,
initialValues,
scope,
unstable_createStore,
unstable_enableVersionedWrite,
}: PropsWithChildren<{
initialValues?: Iterable<readonly [Atom<unknown>, unknown]>
scope?: Scope
/**
* This is an unstable feature to use exported createStore.
*/
unstable_createStore?: typeof createStoreForExport
/**
* This is an unstable experimental feature for React 18.
* When this is enabled, a) write function must be pure
* (read function must be pure regardless of this),
* b) React will show warning in DEV mode,
* c) then state branching works.
*/
unstable_enableVersionedWrite?: boolean
}>) => {
const [version, setVersion] = useState<VersionObject>()
useEffect(() => {
if (version) {
;(scopeContainerRef.current as ScopeContainer).s[COMMIT_ATOM](
null,
version
)
delete version.p
}
}, [version])
const scopeContainerRef = useRef<ScopeContainer>()
if (!scopeContainerRef.current) {
// lazy initialization
scopeContainerRef.current = createScopeContainer(
initialValues,
unstable_createStore
)
if (unstable_enableVersionedWrite) {
scopeContainerRef.current.w = (write) => {
setVersion((parentVersion) => {
const nextVersion = parentVersion ? { p: parentVersion } : {}
write(nextVersion)
return nextVersion
})
}
}
}
// LIMITATION: useDebugState prevents to work versioned write properly
if (__DEV__ && !unstable_enableVersionedWrite) {
// eslint-disable-next-line react-hooks/rules-of-hooks
useDebugState(scopeContainerRef.current)
}
const ScopeContainerContext = getScopeContext(scope)
return createElement(
ScopeContainerContext.Provider,
{
value: scopeContainerRef.current,
},
children
)
}