-
-
Notifications
You must be signed in to change notification settings - Fork 709
Expand file tree
/
Copy pathcontexts.ts
More file actions
74 lines (65 loc) · 2.24 KB
/
contexts.ts
File metadata and controls
74 lines (65 loc) · 2.24 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
import { createContext } from 'react'
import type { Context } from 'react'
import type { Atom, Scope } from './atom'
import { createStore } from './store'
const createScopeContainerForProduction = (
initialValues?: Iterable<readonly [Atom<unknown>, unknown]>
) => {
const store = createStore(initialValues)
return [store] as const
}
const createScopeContainerForDevelopment = (
initialValues?: Iterable<readonly [Atom<unknown>, unknown]>
) => {
const devStore = {
listeners: new Set<() => void>(),
subscribe: (callback: () => void) => {
devStore.listeners.add(callback)
return () => {
devStore.listeners.delete(callback)
}
},
atoms: Array.from(initialValues ?? []).map(([a]) => a),
}
const stateListener = (updatedAtom: Atom<unknown>, isNewAtom: boolean) => {
if (isNewAtom) {
// FIXME memory leak
// we should probably remove unmounted atoms eventually
devStore.atoms = [...devStore.atoms, updatedAtom]
}
Promise.resolve().then(() => {
devStore.listeners.forEach((listener) => listener())
})
}
const store = createStore(initialValues, stateListener)
return [store, devStore] as const
}
export const isDevScopeContainer = (
scopeContainer: ScopeContainer
): scopeContainer is ScopeContainerForDevelopment => {
return scopeContainer.length > 1
}
type ScopeContainerForProduction = ReturnType<
typeof createScopeContainerForProduction
>
export type ScopeContainerForDevelopment = ReturnType<
typeof createScopeContainerForDevelopment
>
export type ScopeContainer =
| ScopeContainerForProduction
| ScopeContainerForDevelopment
type CreateScopeContainer = (
initialValues?: Iterable<readonly [Atom<unknown>, unknown]>
) => ScopeContainer
export const createScopeContainer: CreateScopeContainer =
typeof process === 'object' && process.env.NODE_ENV !== 'production'
? createScopeContainerForDevelopment
: createScopeContainerForProduction
type ScopeContext = Context<ScopeContainer>
const ScopeContextMap = new Map<Scope | undefined, ScopeContext>()
export const getScopeContext = (scope?: Scope) => {
if (!ScopeContextMap.has(scope)) {
ScopeContextMap.set(scope, createContext(createScopeContainer()))
}
return ScopeContextMap.get(scope) as ScopeContext
}