@tamagui/use-store 1.50.0 → 1.50.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/cjs/Store.js +24 -0
- package/dist/cjs/Store.js.map +1 -1
- package/dist/cjs/index.js +7 -2
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/reaction.js +8 -4
- package/dist/cjs/reaction.js.map +1 -1
- package/dist/cjs/selector.js +13 -49
- package/dist/cjs/selector.js.map +2 -2
- package/dist/cjs/useStore.js +68 -38
- package/dist/cjs/useStore.js.map +2 -2
- package/dist/esm/Store.js +24 -0
- package/dist/esm/Store.js.map +1 -1
- package/dist/esm/index.js +6 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/reaction.js +9 -5
- package/dist/esm/reaction.js.map +1 -1
- package/dist/esm/selector.js +14 -49
- package/dist/esm/selector.js.map +2 -2
- package/dist/esm/useStore.js +68 -44
- package/dist/esm/useStore.js.map +2 -2
- package/package.json +2 -2
- package/src/index.ts +5 -1
- package/src/interfaces.tsx +13 -1
- package/src/reaction.tsx +12 -10
- package/src/selector.tsx +60 -52
- package/src/useStore.tsx +93 -59
- package/types/index.d.ts +4 -1
- package/types/index.d.ts.map +1 -1
- package/types/interfaces.d.ts +12 -1
- package/types/interfaces.d.ts.map +1 -1
- package/types/reaction.d.ts +3 -3
- package/types/reaction.d.ts.map +1 -1
- package/types/selector.d.ts +0 -1
- package/types/selector.d.ts.map +1 -1
- package/types/useStore.d.ts +15 -9
- package/types/useStore.d.ts.map +1 -1
- package/src/Store.tsx +0 -50
package/src/selector.tsx
CHANGED
|
@@ -2,7 +2,8 @@ import { useEffect, useState } from 'react'
|
|
|
2
2
|
|
|
3
3
|
import { isEqualSubsetShallow } from './comparators'
|
|
4
4
|
import { UNWRAP_PROXY } from './constants'
|
|
5
|
-
import {
|
|
5
|
+
import { StoreInfo } from './interfaces'
|
|
6
|
+
import { trackStoresAccess } from './useStore'
|
|
6
7
|
|
|
7
8
|
// TODO i think we can just replace reaction() with this, its not worse in any way
|
|
8
9
|
|
|
@@ -25,46 +26,46 @@ const logUpdate =
|
|
|
25
26
|
}
|
|
26
27
|
: null
|
|
27
28
|
|
|
28
|
-
// TODO test this works the same as useSelector
|
|
29
|
-
export function selector(fn: () => any) {
|
|
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
|
-
}
|
|
29
|
+
// // TODO test this works the same as useSelector
|
|
30
|
+
// export function selector(fn: () => any) {
|
|
31
|
+
// let prev = runStoreSelector(fn)
|
|
32
|
+
// let disposeValue: Function | null = null
|
|
33
|
+
// const subscribe = () => {
|
|
34
|
+
// return subscribeToStores([...prev.storeInfos], () => {
|
|
35
|
+
// try {
|
|
36
|
+
// disposeValue?.()
|
|
37
|
+
// setIsInReaction(true)
|
|
38
|
+
// const next = runStoreSelector(fn)
|
|
39
|
+
// if (typeof next.value === 'function') {
|
|
40
|
+
// disposeValue = next.value
|
|
41
|
+
// if (process.env.NODE_ENV === 'development') {
|
|
42
|
+
// logUpdate!(fn, [...next.storeInfos], '(fn)', '(fn)')
|
|
43
|
+
// }
|
|
44
|
+
// return
|
|
45
|
+
// }
|
|
46
|
+
// if (
|
|
47
|
+
// isEqualSubsetShallow(prev.stores, next.stores) &&
|
|
48
|
+
// isEqualSubsetShallow(prev.value, next.value)
|
|
49
|
+
// ) {
|
|
50
|
+
// return
|
|
51
|
+
// }
|
|
52
|
+
// if (process.env.NODE_ENV === 'development') {
|
|
53
|
+
// logUpdate!(fn, [...next.stores], prev.value, next.value)
|
|
54
|
+
// }
|
|
55
|
+
// prev = next
|
|
56
|
+
// dispose()
|
|
57
|
+
// dispose = subscribe()
|
|
58
|
+
// } finally {
|
|
59
|
+
// setIsInReaction(false)
|
|
60
|
+
// }
|
|
61
|
+
// })
|
|
62
|
+
// }
|
|
63
|
+
// let dispose = subscribe()
|
|
64
|
+
// return () => {
|
|
65
|
+
// dispose()
|
|
66
|
+
// disposeValue?.()
|
|
67
|
+
// }
|
|
68
|
+
// }
|
|
68
69
|
|
|
69
70
|
export function useSelector<A>(fn: () => A): A {
|
|
70
71
|
const [state, setState] = useState(() => {
|
|
@@ -73,26 +74,30 @@ export function useSelector<A>(fn: () => A): A {
|
|
|
73
74
|
|
|
74
75
|
useEffect(() => {
|
|
75
76
|
let dispose
|
|
76
|
-
const unsub = subscribeToStores([...state.
|
|
77
|
+
const unsub = subscribeToStores([...state.storeInfos], () => {
|
|
77
78
|
dispose?.()
|
|
78
79
|
const next = runStoreSelector(fn)
|
|
80
|
+
|
|
81
|
+
const nextStoreInfos = [...next.storeInfos]
|
|
82
|
+
const prevStoreInfos = [...state.storeInfos]
|
|
83
|
+
|
|
79
84
|
// return function === return disposable
|
|
80
85
|
if (typeof next.value === 'function') {
|
|
81
86
|
if (process.env.NODE_ENV === 'development') {
|
|
82
|
-
logUpdate!(fn,
|
|
87
|
+
logUpdate!(fn, nextStoreInfos, '(fn)', '(fn)')
|
|
83
88
|
}
|
|
84
89
|
dispose = next.value
|
|
85
90
|
return
|
|
86
91
|
}
|
|
87
92
|
setState((prev) => {
|
|
88
93
|
if (
|
|
89
|
-
isEqualSubsetShallow(
|
|
94
|
+
isEqualSubsetShallow(prevStoreInfos, nextStoreInfos) &&
|
|
90
95
|
isEqualSubsetShallow(prev.value, next.value)
|
|
91
96
|
) {
|
|
92
97
|
return prev
|
|
93
98
|
}
|
|
94
99
|
if (process.env.NODE_ENV === 'development') {
|
|
95
|
-
logUpdate!(fn,
|
|
100
|
+
logUpdate!(fn, nextStoreInfos, prev.value, next.value)
|
|
96
101
|
}
|
|
97
102
|
return next
|
|
98
103
|
})
|
|
@@ -101,25 +106,28 @@ export function useSelector<A>(fn: () => A): A {
|
|
|
101
106
|
unsub()
|
|
102
107
|
dispose?.()
|
|
103
108
|
}
|
|
104
|
-
}, [...state.
|
|
109
|
+
}, [[...state.storeInfos].map((i) => i.uid).join(',')])
|
|
105
110
|
|
|
106
111
|
return state.value
|
|
107
112
|
}
|
|
108
113
|
|
|
109
|
-
function runStoreSelector<A>(selector: () => A): {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
114
|
+
function runStoreSelector<A>(selector: () => A): {
|
|
115
|
+
value: A
|
|
116
|
+
storeInfos: Set<StoreInfo>
|
|
117
|
+
} {
|
|
118
|
+
const storeInfos = new Set<StoreInfo>()
|
|
119
|
+
const dispose = trackStoresAccess((storeInfo) => {
|
|
120
|
+
storeInfos.add(storeInfo)
|
|
113
121
|
})
|
|
114
122
|
const value = selector()
|
|
115
123
|
dispose()
|
|
116
124
|
return {
|
|
117
125
|
value,
|
|
118
|
-
|
|
126
|
+
storeInfos,
|
|
119
127
|
}
|
|
120
128
|
}
|
|
121
129
|
|
|
122
|
-
function subscribeToStores(stores:
|
|
130
|
+
function subscribeToStores(stores: StoreInfo[], onUpdate: () => any) {
|
|
123
131
|
const disposes: Function[] = []
|
|
124
132
|
for (const store of stores) {
|
|
125
133
|
disposes.push(store.subscribe(onUpdate))
|
package/src/useStore.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useCallback,
|
|
1
|
+
import { useCallback, useRef, useSyncExternalStore } from 'react'
|
|
2
2
|
|
|
3
3
|
import { isEqualSubsetShallow } from './comparators'
|
|
4
4
|
import { configureOpts } from './configureUseStore'
|
|
@@ -10,21 +10,13 @@ import {
|
|
|
10
10
|
getStoreUid,
|
|
11
11
|
simpleStr,
|
|
12
12
|
} from './helpers'
|
|
13
|
-
import { Selector, StoreInfo, UseStoreOptions } from './interfaces'
|
|
14
|
-
import {
|
|
15
|
-
SHOULD_DEBUG,
|
|
16
|
-
Store,
|
|
17
|
-
StoreTracker,
|
|
18
|
-
TRIGGER_UPDATE,
|
|
19
|
-
disableTracking,
|
|
20
|
-
setDisableStoreTracking,
|
|
21
|
-
} from './Store'
|
|
22
|
-
import { DebugStores, useCurrentComponent } from './useStoreDebug'
|
|
13
|
+
import { Selector, Store, StoreInfo, UseStoreOptions } from './interfaces'
|
|
14
|
+
import { DebugStores, shouldDebug, useCurrentComponent } from './useStoreDebug'
|
|
23
15
|
|
|
24
16
|
const idFn = (_) => _
|
|
25
17
|
|
|
26
18
|
// no singleton, just react
|
|
27
|
-
export function useStore<A
|
|
19
|
+
export function useStore<A, B extends Object>(
|
|
28
20
|
StoreKlass: (new (props: B) => A) | (new () => A),
|
|
29
21
|
props?: B | null,
|
|
30
22
|
options: UseStoreOptions<A, any> = defaultOptions
|
|
@@ -35,7 +27,7 @@ export function useStore<A extends Store<B>, B extends Object>(
|
|
|
35
27
|
return useStoreFromInfo(info, selector, options)
|
|
36
28
|
}
|
|
37
29
|
|
|
38
|
-
export function useStoreDebug<A
|
|
30
|
+
export function useStoreDebug<A, B extends Object>(
|
|
39
31
|
StoreKlass: (new (props: B) => A) | (new () => A),
|
|
40
32
|
props?: B
|
|
41
33
|
): A {
|
|
@@ -43,7 +35,7 @@ export function useStoreDebug<A extends Store<B>, B extends Object>(
|
|
|
43
35
|
}
|
|
44
36
|
|
|
45
37
|
// singleton
|
|
46
|
-
export function createStore<A
|
|
38
|
+
export function createStore<A, B extends Object>(
|
|
47
39
|
StoreKlass: new (props: B) => A | (new () => A),
|
|
48
40
|
props?: B,
|
|
49
41
|
options?: UseStoreOptions<A, any>
|
|
@@ -56,10 +48,7 @@ export function createStore<A extends Store<B>, B extends Object>(
|
|
|
56
48
|
// use singleton with react
|
|
57
49
|
// TODO selector support with types...
|
|
58
50
|
|
|
59
|
-
export function useGlobalStore<A
|
|
60
|
-
instance: A,
|
|
61
|
-
debug?: boolean
|
|
62
|
-
): A {
|
|
51
|
+
export function useGlobalStore<A, B extends Object>(instance: A, debug?: boolean): A {
|
|
63
52
|
const store = instance[UNWRAP_PROXY]
|
|
64
53
|
const uid = getStoreUid(store.constructor, store.props)
|
|
65
54
|
const info = cache.get(uid)
|
|
@@ -69,11 +58,7 @@ export function useGlobalStore<A extends Store<B>, B extends Object>(
|
|
|
69
58
|
return useStoreFromInfo(info, undefined, { debug })
|
|
70
59
|
}
|
|
71
60
|
|
|
72
|
-
export function useGlobalStoreSelector<
|
|
73
|
-
A extends Store<B>,
|
|
74
|
-
B extends Object,
|
|
75
|
-
Selector extends (store: A) => any
|
|
76
|
-
>(
|
|
61
|
+
export function useGlobalStoreSelector<A, Selector extends (store: A) => any>(
|
|
77
62
|
instance: A,
|
|
78
63
|
selector: Selector,
|
|
79
64
|
debug?: boolean
|
|
@@ -127,7 +112,7 @@ export function useStoreSelector<
|
|
|
127
112
|
return useStore(StoreKlass, props, { selector }) as any
|
|
128
113
|
}
|
|
129
114
|
|
|
130
|
-
type StoreAccessTracker = (store:
|
|
115
|
+
type StoreAccessTracker = (store: StoreInfo) => void
|
|
131
116
|
const storeAccessTrackers = new Set<StoreAccessTracker>()
|
|
132
117
|
export function trackStoresAccess(cb: StoreAccessTracker) {
|
|
133
118
|
storeAccessTrackers.add(cb)
|
|
@@ -136,27 +121,38 @@ export function trackStoresAccess(cb: StoreAccessTracker) {
|
|
|
136
121
|
}
|
|
137
122
|
}
|
|
138
123
|
|
|
139
|
-
|
|
140
|
-
export function getStore<A extends Store<B>, B extends Object>(
|
|
124
|
+
export function getStore<A, B extends Object>(
|
|
141
125
|
StoreKlass: (new (props: B) => A) | (new () => A),
|
|
142
126
|
props?: B
|
|
143
127
|
): A {
|
|
144
|
-
return
|
|
128
|
+
return getStoreInfo(StoreKlass, props).store as any
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// just like getOrCreateStoreInfo but refuses to create
|
|
132
|
+
export function getStoreInfo(StoreKlass: any, props: any) {
|
|
133
|
+
return getOrCreateStoreInfo(StoreKlass, props, {
|
|
134
|
+
refuseCreation: true,
|
|
135
|
+
})
|
|
145
136
|
}
|
|
146
137
|
|
|
147
138
|
function getOrCreateStoreInfo(
|
|
148
139
|
StoreKlass: any,
|
|
149
140
|
props: any,
|
|
150
|
-
options?: UseStoreOptions & { avoidCache?: boolean },
|
|
141
|
+
options?: UseStoreOptions & { avoidCache?: boolean; refuseCreation?: boolean },
|
|
151
142
|
propsKeyCalculated?: string
|
|
152
143
|
) {
|
|
153
144
|
const uid = getStoreUid(StoreKlass, propsKeyCalculated ?? props)
|
|
154
145
|
if (!options?.avoidCache && cache.has(uid)) {
|
|
155
146
|
return cache.get(uid)!
|
|
156
147
|
}
|
|
148
|
+
if (options?.refuseCreation) {
|
|
149
|
+
throw new Error(`No store exists (${StoreKlass.name}) with props: ${props}`)
|
|
150
|
+
}
|
|
157
151
|
|
|
158
152
|
// init
|
|
159
153
|
const storeInstance = new StoreKlass(props!)
|
|
154
|
+
// add props
|
|
155
|
+
storeInstance.props = props
|
|
160
156
|
|
|
161
157
|
const getters = {}
|
|
162
158
|
const actions = {}
|
|
@@ -177,22 +173,44 @@ function getOrCreateStoreInfo(
|
|
|
177
173
|
}
|
|
178
174
|
|
|
179
175
|
const keyComparators = storeInstance['_comparators']
|
|
176
|
+
const listeners = new Set<Function>()
|
|
177
|
+
|
|
180
178
|
const storeInfo = {
|
|
179
|
+
uid: Math.random(),
|
|
181
180
|
keyComparators,
|
|
182
181
|
storeInstance,
|
|
183
182
|
getters,
|
|
184
183
|
stateKeys,
|
|
185
184
|
actions,
|
|
186
185
|
debug: options?.debug,
|
|
186
|
+
disableTracking: false,
|
|
187
187
|
gettersState: {
|
|
188
188
|
getCache: new Map<string, any>(),
|
|
189
189
|
depsToGetter: new Map<string, Set<string>>(),
|
|
190
190
|
curGetKeys: new Set<string>(),
|
|
191
191
|
isGetting: false,
|
|
192
192
|
},
|
|
193
|
-
|
|
193
|
+
listeners,
|
|
194
|
+
trackers: new Set(),
|
|
195
|
+
version: 0,
|
|
196
|
+
subscribe: (onChanged: Function) => {
|
|
197
|
+
listeners.add(onChanged)
|
|
198
|
+
return () => {
|
|
199
|
+
listeners.delete(onChanged)
|
|
200
|
+
}
|
|
201
|
+
},
|
|
202
|
+
triggerUpdate: () => {
|
|
203
|
+
storeInfo.version = (storeInfo.version + 1) % Number.MAX_SAFE_INTEGER
|
|
204
|
+
for (const cb of listeners) {
|
|
205
|
+
cb()
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
} satisfies Omit<StoreInfo, 'store'>
|
|
194
209
|
|
|
195
|
-
const store = createProxiedStore(
|
|
210
|
+
const store = createProxiedStore(
|
|
211
|
+
// we assign store right after and proxiedStore never accesses it until later on
|
|
212
|
+
storeInfo as any as StoreInfo
|
|
213
|
+
)
|
|
196
214
|
|
|
197
215
|
// uses more memory when on
|
|
198
216
|
if (process.env.NODE_ENV === 'development') {
|
|
@@ -202,15 +220,15 @@ function getOrCreateStoreInfo(
|
|
|
202
220
|
// if has a mount function call it
|
|
203
221
|
store.mount?.()
|
|
204
222
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
223
|
+
// @ts-ignore
|
|
224
|
+
storeInfo.store = store
|
|
225
|
+
|
|
226
|
+
const result = storeInfo as any as StoreInfo
|
|
209
227
|
|
|
210
228
|
// still set even when avoidCache is true (hmr)
|
|
211
|
-
cache.set(uid,
|
|
229
|
+
cache.set(uid, result)
|
|
212
230
|
|
|
213
|
-
return
|
|
231
|
+
return result
|
|
214
232
|
}
|
|
215
233
|
|
|
216
234
|
export const allStores = {}
|
|
@@ -257,7 +275,7 @@ function useStoreFromInfo(
|
|
|
257
275
|
const getSnapshot = useCallback(() => {
|
|
258
276
|
const curInternal = internal.current!
|
|
259
277
|
const keys = [...(!curInternal.tracked.size ? info.stateKeys : curInternal.tracked)]
|
|
260
|
-
const nextKeys = `${
|
|
278
|
+
const nextKeys = `${info.version}${keys.join('')}${userSelector || ''}`
|
|
261
279
|
const lastKeys = curInternal.lastKeys
|
|
262
280
|
|
|
263
281
|
// avoid updates
|
|
@@ -269,14 +287,14 @@ function useStoreFromInfo(
|
|
|
269
287
|
|
|
270
288
|
let snap: any
|
|
271
289
|
// dont track during selector
|
|
272
|
-
|
|
290
|
+
info.disableTracking = true
|
|
273
291
|
const last = curInternal.last
|
|
274
292
|
if (userSelector) {
|
|
275
293
|
snap = userSelector(store)
|
|
276
294
|
} else {
|
|
277
295
|
snap = selectKeys(store, keys)
|
|
278
296
|
}
|
|
279
|
-
|
|
297
|
+
info.disableTracking = false
|
|
280
298
|
|
|
281
299
|
// this wasn't updating in AnimationsStore
|
|
282
300
|
const isUnchanged =
|
|
@@ -300,7 +318,7 @@ function useStoreFromInfo(
|
|
|
300
318
|
}, [])
|
|
301
319
|
|
|
302
320
|
// sync by default
|
|
303
|
-
const state = useSyncExternalStore(
|
|
321
|
+
const state = useSyncExternalStore(info.subscribe, getSnapshot, getSnapshot)
|
|
304
322
|
|
|
305
323
|
if (userSelector) {
|
|
306
324
|
return state
|
|
@@ -315,6 +333,7 @@ function useStoreFromInfo(
|
|
|
315
333
|
return curVal
|
|
316
334
|
}
|
|
317
335
|
const keyString = key as string // fine for our uses
|
|
336
|
+
|
|
318
337
|
if (info.stateKeys.has(keyString) || keyString in info.getters) {
|
|
319
338
|
if (shouldPrintDebug) {
|
|
320
339
|
// rome-ignore lint/nursery/noConsoleLog: <explanation>
|
|
@@ -333,14 +352,13 @@ function useStoreFromInfo(
|
|
|
333
352
|
let setters = new Set<any>()
|
|
334
353
|
const logStack = new Set<Set<any[]> | 'end'>()
|
|
335
354
|
|
|
336
|
-
function createProxiedStore(storeInfo:
|
|
355
|
+
function createProxiedStore(storeInfo: StoreInfo) {
|
|
337
356
|
const { actions, storeInstance, getters, gettersState } = storeInfo
|
|
338
357
|
const { getCache, curGetKeys, depsToGetter } = gettersState
|
|
339
358
|
const constr = storeInstance.constructor
|
|
340
359
|
const shouldDebug = storeInfo.debug ?? DebugStores.has(constr)
|
|
341
360
|
|
|
342
361
|
let didSet = false
|
|
343
|
-
let isInAction = false
|
|
344
362
|
const wrappedActions = {}
|
|
345
363
|
|
|
346
364
|
// pre-setup actions
|
|
@@ -364,10 +382,8 @@ function createProxiedStore(storeInfo: Omit<StoreInfo, 'store' | 'source'>) {
|
|
|
364
382
|
}
|
|
365
383
|
if (process.env.NODE_ENV === 'development' && shouldDebug) {
|
|
366
384
|
// rome-ignore lint/nursery/noConsoleLog: <explanation>
|
|
367
|
-
console.log('(debug) startAction', key
|
|
385
|
+
console.log('(debug) startAction', key)
|
|
368
386
|
}
|
|
369
|
-
// dumb for now
|
|
370
|
-
isInAction = true
|
|
371
387
|
res = Reflect.apply(actionFn, proxiedStore, args)
|
|
372
388
|
if (res instanceof Promise) {
|
|
373
389
|
return res.then(finishAction)
|
|
@@ -502,9 +518,8 @@ function createProxiedStore(storeInfo: Omit<StoreInfo, 'store' | 'source'>) {
|
|
|
502
518
|
// rome-ignore lint/nursery/noConsoleLog: <explanation>
|
|
503
519
|
console.log('(debug) finishAction', { didSet })
|
|
504
520
|
}
|
|
505
|
-
isInAction = false
|
|
506
521
|
if (didSet) {
|
|
507
|
-
|
|
522
|
+
storeInfo.triggerUpdate()
|
|
508
523
|
didSet = false
|
|
509
524
|
}
|
|
510
525
|
return val
|
|
@@ -528,11 +543,11 @@ function createProxiedStore(storeInfo: Omit<StoreInfo, 'store' | 'source'>) {
|
|
|
528
543
|
if (key === UNWRAP_STORE_INFO) {
|
|
529
544
|
return storeInfo
|
|
530
545
|
}
|
|
531
|
-
const trackingDisabled = disableTracking
|
|
546
|
+
const trackingDisabled = storeInfo.disableTracking
|
|
532
547
|
if (!trackingDisabled) {
|
|
533
548
|
if (storeAccessTrackers.size && !storeAccessTrackers.has(storeInstance)) {
|
|
534
549
|
for (const t of storeAccessTrackers) {
|
|
535
|
-
t(
|
|
550
|
+
t(storeInfo)
|
|
536
551
|
}
|
|
537
552
|
}
|
|
538
553
|
}
|
|
@@ -585,6 +600,7 @@ function createProxiedStore(storeInfo: Omit<StoreInfo, 'store' | 'source'>) {
|
|
|
585
600
|
set(target, key, value, receiver) {
|
|
586
601
|
const cur = Reflect.get(target, key)
|
|
587
602
|
const res = Reflect.set(target, key, value, receiver)
|
|
603
|
+
|
|
588
604
|
// only update if changed, simple compare
|
|
589
605
|
if (res && cur !== value) {
|
|
590
606
|
// clear getters cache that rely on this
|
|
@@ -593,21 +609,21 @@ function createProxiedStore(storeInfo: Omit<StoreInfo, 'store' | 'source'>) {
|
|
|
593
609
|
}
|
|
594
610
|
if (shouldDebug) {
|
|
595
611
|
setters.add({ key, value })
|
|
596
|
-
if (
|
|
612
|
+
if (getShouldDebug(storeInfo)) {
|
|
597
613
|
// rome-ignore lint/nursery/noConsoleLog: <explanation>
|
|
598
614
|
console.log('(debug) SET', res, key, value)
|
|
599
615
|
}
|
|
600
616
|
}
|
|
601
617
|
if (process.env.NODE_ENV === 'development' && shouldDebug) {
|
|
602
618
|
// rome-ignore lint/nursery/noConsoleLog: <explanation>
|
|
603
|
-
console.log('SET...', { key, value
|
|
619
|
+
console.log('SET...', { key, value })
|
|
604
620
|
}
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
621
|
+
|
|
622
|
+
if (!isTriggering) {
|
|
623
|
+
// trigger only once per event loop
|
|
608
624
|
isTriggering = true
|
|
609
|
-
|
|
610
|
-
|
|
625
|
+
waitForEventLoop(() => {
|
|
626
|
+
storeInfo.triggerUpdate()
|
|
611
627
|
isTriggering = false
|
|
612
628
|
})
|
|
613
629
|
}
|
|
@@ -617,12 +633,12 @@ function createProxiedStore(storeInfo: Omit<StoreInfo, 'store' | 'source'>) {
|
|
|
617
633
|
})
|
|
618
634
|
|
|
619
635
|
function clearGetterCache(setKey: string) {
|
|
620
|
-
const
|
|
636
|
+
const parentGetters = depsToGetter.get(setKey)
|
|
621
637
|
getCache.delete(setKey)
|
|
622
|
-
if (!
|
|
638
|
+
if (!parentGetters) {
|
|
623
639
|
return
|
|
624
640
|
}
|
|
625
|
-
for (const gk of
|
|
641
|
+
for (const gk of parentGetters) {
|
|
626
642
|
getCache.delete(gk)
|
|
627
643
|
if (depsToGetter.has(gk)) {
|
|
628
644
|
clearGetterCache(gk)
|
|
@@ -633,6 +649,9 @@ function createProxiedStore(storeInfo: Omit<StoreInfo, 'store' | 'source'>) {
|
|
|
633
649
|
return proxiedStore
|
|
634
650
|
}
|
|
635
651
|
|
|
652
|
+
const waitForEventLoop =
|
|
653
|
+
process.env.NODE_ENV === 'test' ? (cb: Function) => cb() : queueMicrotask
|
|
654
|
+
|
|
636
655
|
let counter = 0
|
|
637
656
|
|
|
638
657
|
const passThroughKeys = {
|
|
@@ -643,3 +662,18 @@ const passThroughKeys = {
|
|
|
643
662
|
_listeners: true,
|
|
644
663
|
_enableTracking: true,
|
|
645
664
|
}
|
|
665
|
+
|
|
666
|
+
export type StoreTracker = {
|
|
667
|
+
tracked: Set<string>
|
|
668
|
+
component?: any
|
|
669
|
+
last?: any
|
|
670
|
+
lastKeys?: any
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
function getShouldDebug(storeInfo: StoreInfo) {
|
|
674
|
+
const info = { storeInstance: storeInfo.store }
|
|
675
|
+
const trackers = storeInfo.trackers
|
|
676
|
+
return [...trackers].some(
|
|
677
|
+
(tracker) => tracker.component && shouldDebug(tracker.component, info)
|
|
678
|
+
)
|
|
679
|
+
}
|
package/types/index.d.ts
CHANGED
|
@@ -3,8 +3,11 @@ export { configureUseStore } from './configureUseStore';
|
|
|
3
3
|
export * from './interfaces';
|
|
4
4
|
export * from './selector';
|
|
5
5
|
export * from './reaction';
|
|
6
|
-
export * from './Store';
|
|
7
6
|
export { UNWRAP_PROXY } from './constants';
|
|
8
7
|
export * from './comparators';
|
|
9
8
|
export * from './decorators';
|
|
9
|
+
export declare class Store<Props extends Record<string, any>> {
|
|
10
|
+
props: Props;
|
|
11
|
+
constructor(props: Props);
|
|
12
|
+
}
|
|
10
13
|
//# sourceMappingURL=index.d.ts.map
|
package/types/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAC1B,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AACvD,cAAc,cAAc,CAAA;AAC5B,cAAc,YAAY,CAAA;AAC1B,cAAc,YAAY,CAAA;AAC1B,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAC1B,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AACvD,cAAc,cAAc,CAAA;AAC5B,cAAc,YAAY,CAAA;AAC1B,cAAc,YAAY,CAAA;AAC1B,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC1C,cAAc,eAAe,CAAA;AAC7B,cAAc,cAAc,CAAA;AAG5B,qBAAa,KAAK,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAC/B,KAAK,EAAE,KAAK;gBAAZ,KAAK,EAAE,KAAK;CAChC"}
|
package/types/interfaces.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { StoreTracker } from './useStore';
|
|
2
2
|
export type Selector<A = unknown, B = unknown> = (x: A) => B;
|
|
3
3
|
export type UseStoreSelector<Store, Res> = (store: Store) => Res;
|
|
4
4
|
export type UseStoreOptions<Store = any, SelectorRes = any> = {
|
|
@@ -6,7 +6,12 @@ export type UseStoreOptions<Store = any, SelectorRes = any> = {
|
|
|
6
6
|
selector?: UseStoreSelector<Store, SelectorRes>;
|
|
7
7
|
once?: boolean;
|
|
8
8
|
};
|
|
9
|
+
export interface Store<Props = Record<string, any> | null | undefined> {
|
|
10
|
+
new (...args: any[]): any;
|
|
11
|
+
props: Props;
|
|
12
|
+
}
|
|
9
13
|
export type StoreInfo<A = Store> = {
|
|
14
|
+
uid: number;
|
|
10
15
|
keyComparators?: {
|
|
11
16
|
[key: string]: (a: any, b: any) => boolean;
|
|
12
17
|
};
|
|
@@ -24,6 +29,12 @@ export type StoreInfo<A = Store> = {
|
|
|
24
29
|
curGetKeys: Set<string>;
|
|
25
30
|
isGetting: boolean;
|
|
26
31
|
};
|
|
32
|
+
listeners: Set<Function>;
|
|
33
|
+
trackers: Set<StoreTracker>;
|
|
34
|
+
version: number;
|
|
35
|
+
subscribe: (onChanged: () => void) => () => void;
|
|
36
|
+
triggerUpdate: Function;
|
|
37
|
+
disableTracking: boolean;
|
|
27
38
|
};
|
|
28
39
|
export type UseStoreConfig = {
|
|
29
40
|
logLevel?: 'debug' | 'info' | 'error';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../src/interfaces.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../src/interfaces.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAEzC,MAAM,MAAM,QAAQ,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAA;AAE5D,MAAM,MAAM,gBAAgB,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,KAAK,EAAE,KAAK,KAAK,GAAG,CAAA;AAChE,MAAM,MAAM,eAAe,CAAC,KAAK,GAAG,GAAG,EAAE,WAAW,GAAG,GAAG,IAAI;IAC5D,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,QAAQ,CAAC,EAAE,gBAAgB,CAAC,KAAK,EAAE,WAAW,CAAC,CAAA;IAC/C,IAAI,CAAC,EAAE,OAAO,CAAA;CACf,CAAA;AAED,MAAM,WAAW,KAAK,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,GAAG,SAAS;IACnE,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,GAAG,CAAA;IACzB,KAAK,EAAE,KAAK,CAAA;CACb;AAED,MAAM,MAAM,SAAS,CAAC,CAAC,GAAG,KAAK,IAAI;IACjC,GAAG,EAAE,MAAM,CAAA;IACX,cAAc,CAAC,EAAE;QACf,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,KAAK,OAAO,CAAA;KAC3C,CAAA;IAED,KAAK,EAAE,CAAC,CAAA;IACR,aAAa,EAAE,GAAG,CAAA;IAClB,OAAO,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAE,CAAA;IAC/B,OAAO,EAAE,GAAG,CAAA;IACZ,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IACtB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,YAAY,EAAE;QACZ,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;QAC1B,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAA;QACtC,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;QACvB,SAAS,EAAE,OAAO,CAAA;KACnB,CAAA;IACD,SAAS,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAA;IACxB,QAAQ,EAAE,GAAG,CAAC,YAAY,CAAC,CAAA;IAC3B,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,CAAC,SAAS,EAAE,MAAM,IAAI,KAAK,MAAM,IAAI,CAAA;IAChD,aAAa,EAAE,QAAQ,CAAA;IACvB,eAAe,EAAE,OAAO,CAAA;CACzB,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,CAAA;CACtC,CAAA"}
|
package/types/reaction.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare function useReaction<StoreInstance
|
|
3
|
-
export declare function reaction<StoreInstance extends
|
|
1
|
+
import { StoreInfo } from './interfaces';
|
|
2
|
+
export declare function useReaction<StoreInstance, Selector extends (a: StoreInstance) => any>(store: StoreInstance, selector: Selector, receiver: Selector extends (a: StoreInstance) => infer Derived ? (a: Derived) => any : unknown, props?: Record<string, any>, equalityFn?: (a: any, b: any) => boolean, memoArgs?: any[]): () => void;
|
|
3
|
+
export declare function reaction<StoreInstance extends StoreInfo, Selector extends (a: StoreInstance) => any>({ store, subscribe }: StoreInstance, selector: Selector, receiver: Selector extends (a: StoreInstance) => infer Derived ? (a: Derived) => any : unknown, equalityFn?: (a: any, b: any) => boolean): () => void;
|
|
4
4
|
//# sourceMappingURL=reaction.d.ts.map
|
package/types/reaction.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reaction.d.ts","sourceRoot":"","sources":["../src/reaction.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"reaction.d.ts","sourceRoot":"","sources":["../src/reaction.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AASxC,wBAAgB,WAAW,CAAC,aAAa,EAAE,QAAQ,SAAS,CAAC,CAAC,EAAE,aAAa,KAAK,GAAG,EACnF,KAAK,EAAE,aAAa,EACpB,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,QAAQ,SAAS,CAAC,CAAC,EAAE,aAAa,KAAK,MAAM,OAAO,GAC1D,CAAC,CAAC,EAAE,OAAO,KAAK,GAAG,GACnB,OAAO,EACX,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC3B,UAAU,GAAE,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,KAAK,OAA8B,EAC9D,QAAQ,CAAC,EAAE,GAAG,EAAE,cAOjB;AAED,wBAAgB,QAAQ,CACtB,aAAa,SAAS,SAAS,EAC/B,QAAQ,SAAS,CAAC,CAAC,EAAE,aAAa,KAAK,GAAG,EAE1C,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,aAAa,EACnC,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,QAAQ,SAAS,CAAC,CAAC,EAAE,aAAa,KAAK,MAAM,OAAO,GAC1D,CAAC,CAAC,EAAE,OAAO,KAAK,GAAG,GACnB,OAAO,EACX,UAAU,GAAE,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,KAAK,OAA8B,cAyC/D"}
|
package/types/selector.d.ts
CHANGED
package/types/selector.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"selector.d.ts","sourceRoot":"","sources":["../src/selector.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"selector.d.ts","sourceRoot":"","sources":["../src/selector.tsx"],"names":[],"mappings":"AAqEA,wBAAgB,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CA0C7C"}
|
package/types/useStore.d.ts
CHANGED
|
@@ -1,17 +1,23 @@
|
|
|
1
|
-
import { Selector, UseStoreOptions } from './interfaces';
|
|
2
|
-
|
|
3
|
-
export declare function
|
|
4
|
-
export declare function
|
|
5
|
-
export declare function
|
|
6
|
-
export declare function
|
|
7
|
-
export declare function useGlobalStoreSelector<A extends Store<B>, B extends Object, Selector extends (store: A) => any>(instance: A, selector: Selector, debug?: boolean): Selector extends (a: A) => infer C ? C : unknown;
|
|
1
|
+
import { Selector, Store, StoreInfo, UseStoreOptions } from './interfaces';
|
|
2
|
+
export declare function useStore<A, B extends Object>(StoreKlass: (new (props: B) => A) | (new () => A), props?: B | null, options?: UseStoreOptions<A, any>): A;
|
|
3
|
+
export declare function useStoreDebug<A, B extends Object>(StoreKlass: (new (props: B) => A) | (new () => A), props?: B): A;
|
|
4
|
+
export declare function createStore<A, B extends Object>(StoreKlass: new (props: B) => A | (new () => A), props?: B, options?: UseStoreOptions<A, any>): A;
|
|
5
|
+
export declare function useGlobalStore<A, B extends Object>(instance: A, debug?: boolean): A;
|
|
6
|
+
export declare function useGlobalStoreSelector<A, Selector extends (store: A) => any>(instance: A, selector: Selector, debug?: boolean): Selector extends (a: A) => infer C ? C : unknown;
|
|
8
7
|
export declare function createUseStore<Props, Store>(StoreKlass: (new (props: Props) => Store) | (new () => Store)): <Res, C extends Selector<Store, Res>, Props_1 extends Object>(props?: Props_1 | undefined, options?: UseStoreOptions) => C extends Selector<any, infer B> ? B extends Object ? B : Store : Store;
|
|
9
8
|
export declare function createUseStoreSelector<A extends Store<Props>, Props extends Object, Selected>(StoreKlass: (new (props: Props) => A) | (new () => A), selector: Selector<A, Selected>): (props?: Props) => Selected;
|
|
10
9
|
export declare function useStoreSelector<A extends Store<B>, B extends Object, S extends Selector<A, any>>(StoreKlass: (new (props: B) => A) | (new () => A), selector: S, props?: B): S extends Selector<any, infer R> ? R : unknown;
|
|
11
|
-
type StoreAccessTracker = (store:
|
|
10
|
+
type StoreAccessTracker = (store: StoreInfo) => void;
|
|
12
11
|
export declare function trackStoresAccess(cb: StoreAccessTracker): () => void;
|
|
13
|
-
export declare function getStore<A
|
|
12
|
+
export declare function getStore<A, B extends Object>(StoreKlass: (new (props: B) => A) | (new () => A), props?: B): A;
|
|
13
|
+
export declare function getStoreInfo(StoreKlass: any, props: any): StoreInfo;
|
|
14
14
|
export declare const allStores: {};
|
|
15
15
|
export declare const setIsInReaction: (val: boolean) => void;
|
|
16
|
+
export type StoreTracker = {
|
|
17
|
+
tracked: Set<string>;
|
|
18
|
+
component?: any;
|
|
19
|
+
last?: any;
|
|
20
|
+
lastKeys?: any;
|
|
21
|
+
};
|
|
16
22
|
export {};
|
|
17
23
|
//# sourceMappingURL=useStore.d.ts.map
|