muya 1.0.3 → 2.0.0-beta.1

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.
Files changed (89) hide show
  1. package/README.md +194 -216
  2. package/cjs/index.js +1 -1
  3. package/esm/__tests__/create-async.test.js +1 -0
  4. package/esm/create.js +1 -1
  5. package/esm/index.js +1 -1
  6. package/esm/subscriber.js +1 -0
  7. package/esm/types.js +1 -1
  8. package/esm/use.js +1 -0
  9. package/esm/utils/__tests__/context.test.js +1 -0
  10. package/esm/utils/__tests__/is.test.js +1 -0
  11. package/esm/utils/__tests__/sub-memo.test.js +1 -0
  12. package/esm/utils/common.js +1 -0
  13. package/esm/utils/create-context.js +1 -0
  14. package/esm/utils/create-emitter.js +1 -0
  15. package/esm/utils/is.js +1 -0
  16. package/esm/utils/scheduler.js +1 -0
  17. package/esm/utils/shallow.js +1 -0
  18. package/esm/utils/sub-memo.js +1 -0
  19. package/package.json +1 -4
  20. package/packages/core/__tests__/bench.test.tsx +261 -0
  21. package/packages/core/__tests__/create-async.test.ts +88 -0
  22. package/packages/core/__tests__/create.test.tsx +107 -0
  23. package/packages/core/__tests__/use-async.test.tsx +44 -0
  24. package/packages/core/__tests__/use.test.tsx +76 -0
  25. package/packages/core/create.ts +67 -0
  26. package/packages/core/index.ts +4 -0
  27. package/packages/core/subscriber.ts +121 -0
  28. package/packages/core/types.ts +15 -0
  29. package/packages/core/use.ts +59 -0
  30. package/packages/core/utils/__tests__/context.test.ts +198 -0
  31. package/{src → packages/core/utils}/__tests__/is.test.ts +1 -30
  32. package/packages/core/utils/__tests__/sub-memo.test.ts +13 -0
  33. package/packages/core/utils/common.ts +48 -0
  34. package/packages/core/utils/create-context.ts +60 -0
  35. package/packages/core/utils/create-emitter.ts +53 -0
  36. package/{src → packages/core/utils}/is.ts +11 -13
  37. package/packages/core/utils/scheduler.ts +59 -0
  38. package/{src → packages/core/utils}/shallow.ts +3 -3
  39. package/packages/core/utils/sub-memo.ts +37 -0
  40. package/types/create.d.ts +14 -21
  41. package/types/index.d.ts +2 -4
  42. package/types/subscriber.d.ts +25 -0
  43. package/types/types.d.ts +9 -65
  44. package/types/use.d.ts +2 -0
  45. package/types/utils/common.d.ts +15 -0
  46. package/types/utils/create-context.d.ts +5 -0
  47. package/types/utils/create-emitter.d.ts +20 -0
  48. package/types/{is.d.ts → utils/is.d.ts} +5 -6
  49. package/types/utils/scheduler.d.ts +6 -0
  50. package/types/utils/sub-memo.d.ts +6 -0
  51. package/esm/__tests__/common.test.js +0 -1
  52. package/esm/__tests__/is.test.js +0 -1
  53. package/esm/__tests__/merge.test.js +0 -1
  54. package/esm/__tests__/types.test.js +0 -1
  55. package/esm/common.js +0 -1
  56. package/esm/create-base-state.js +0 -1
  57. package/esm/create-emitter.js +0 -1
  58. package/esm/create-getter-state.js +0 -1
  59. package/esm/is.js +0 -1
  60. package/esm/merge.js +0 -1
  61. package/esm/select.js +0 -1
  62. package/esm/shallow.js +0 -1
  63. package/esm/use-state-value.js +0 -1
  64. package/src/__tests__/common.test.ts +0 -63
  65. package/src/__tests__/create.test.tsx +0 -84
  66. package/src/__tests__/merge.test.ts +0 -78
  67. package/src/__tests__/state.test.tsx +0 -619
  68. package/src/__tests__/types.test.ts +0 -17
  69. package/src/common.ts +0 -60
  70. package/src/create-base-state.ts +0 -31
  71. package/src/create-emitter.ts +0 -24
  72. package/src/create-getter-state.ts +0 -18
  73. package/src/create.ts +0 -127
  74. package/src/index.ts +0 -6
  75. package/src/merge.ts +0 -38
  76. package/src/select.ts +0 -33
  77. package/src/types.ts +0 -94
  78. package/src/use-state-value.ts +0 -32
  79. package/types/common.d.ts +0 -17
  80. package/types/create-base-state.d.ts +0 -10
  81. package/types/create-emitter.d.ts +0 -7
  82. package/types/create-getter-state.d.ts +0 -6
  83. package/types/merge.d.ts +0 -4
  84. package/types/select.d.ts +0 -2
  85. package/types/use-state-value.d.ts +0 -10
  86. /package/esm/{__tests__ → utils/__tests__}/shallow.test.js +0 -0
  87. /package/{src → packages/core}/__tests__/test-utils.ts +0 -0
  88. /package/{src → packages/core/utils}/__tests__/shallow.test.ts +0 -0
  89. /package/types/{shallow.d.ts → utils/shallow.d.ts} +0 -0
@@ -1,619 +0,0 @@
1
- /* eslint-disable @typescript-eslint/no-shadow */
2
- /* eslint-disable no-shadow */
3
- import { Suspense } from 'react'
4
- import { create } from '../create'
5
- import { renderHook, act, waitFor, render, screen } from '@testing-library/react'
6
- import { shallow } from '../shallow'
7
- describe('state', () => {
8
- it('should test state', () => {
9
- const appState = create({ count: 0 })
10
- expect(appState.getState()).toEqual({ count: 0 })
11
- })
12
-
13
- it('should render state with promise hook', async () => {
14
- const promise = Promise.resolve({ count: 100 })
15
- const appState = create(promise)
16
- const renderCount = { current: 0 }
17
- // const
18
-
19
- const result = renderHook(() => {
20
- renderCount.current++
21
- return appState()
22
- })
23
- // wait for the promise to be resolved
24
- await waitFor(() => {})
25
- expect(result.result.current).toEqual({ count: 100 })
26
- // count rendered
27
- expect(renderCount.current).toEqual(2)
28
- expect(appState.getState()).toEqual({ count: 100 })
29
- })
30
-
31
- it('should render state with get promise hook', async () => {
32
- // eslint-disable-next-line unicorn/consistent-function-scoping
33
- const getPromise = () => Promise.resolve({ count: 100 })
34
- const appState = create(getPromise)
35
- const renderCount = { current: 0 }
36
- // const
37
-
38
- const result = renderHook(() => {
39
- renderCount.current++
40
- return appState()
41
- })
42
- // wait for the promise to be resolved
43
- await waitFor(() => {})
44
- act(() => {
45
- appState.setState({ count: 15 })
46
- })
47
- expect(result.result.current).toEqual({ count: 15 })
48
- // count rendered
49
- expect(renderCount.current).toEqual(3)
50
- expect(appState.getState()).toEqual({ count: 15 })
51
- })
52
-
53
- it('should render state with get promise check default', async () => {
54
- // eslint-disable-next-line unicorn/consistent-function-scoping
55
- const getPromise = () => Promise.resolve({ count: 100 })
56
- const appState = create(getPromise)
57
- // const
58
-
59
- // wait for the promise to be resolved
60
- await waitFor(() => {})
61
- act(() => {
62
- appState.setState({ count: 15 })
63
- })
64
- expect(appState.getState()).toEqual({ count: 15 })
65
- // count rendered
66
- act(() => {
67
- appState.reset()
68
- })
69
- expect(appState.getState()).toEqual({ count: 15 })
70
- })
71
-
72
- it('should render state with get hook', async () => {
73
- // eslint-disable-next-line unicorn/consistent-function-scoping
74
- const get = () => ({ count: 100 })
75
- const appState = create(get)
76
- const renderCount = { current: 0 }
77
- // const
78
-
79
- const result = renderHook(() => {
80
- renderCount.current++
81
- return appState()
82
- })
83
- // wait for the promise to be resolved
84
- await waitFor(() => {})
85
- act(() => {
86
- appState.setState({ count: 15 })
87
- })
88
- expect(result.result.current).toEqual({ count: 15 })
89
- // count rendered
90
- expect(renderCount.current).toEqual(2)
91
- expect(appState.getState()).toEqual({ count: 15 })
92
-
93
- act(() => {
94
- appState.reset()
95
- })
96
- expect(result.result.current).toEqual({ count: 100 })
97
- })
98
-
99
- it('should render state with get', async () => {
100
- let wasCalled = false
101
- const get = () => {
102
- wasCalled = true
103
- return { count: 100 }
104
- }
105
- const appState = create(get)
106
- expect(wasCalled).toEqual(false)
107
- appState.getState()
108
- expect(wasCalled).toEqual(true)
109
- })
110
- it('should render state with get hook', async () => {
111
- let wasCalled = false
112
- const get = () => {
113
- wasCalled = true
114
- return { count: 100 }
115
- }
116
- const appState = create(get)
117
- expect(wasCalled).toEqual(false)
118
- renderHook(() => {
119
- appState()
120
- })
121
- expect(wasCalled).toEqual(true)
122
- })
123
-
124
- it('should render state with promise with suspense', async () => {
125
- const promise = Promise.resolve({ count: 100 })
126
- const appState = create(promise)
127
- const renderCount = { current: 0 }
128
-
129
- const MockedComponent = jest.fn(() => <div>loading</div>)
130
- const MockedComponentAfterSuspense = jest.fn(() => <div>loaded</div>)
131
- // const
132
- function Component() {
133
- renderCount.current++
134
- return (
135
- <div>
136
- {appState().count}
137
- <MockedComponentAfterSuspense />
138
- </div>
139
- )
140
- }
141
- render(
142
- <Suspense fallback={<MockedComponent />}>
143
- <Component />
144
- </Suspense>,
145
- )
146
- expect(MockedComponent).toHaveBeenCalledTimes(1)
147
- expect(MockedComponentAfterSuspense).toHaveBeenCalledTimes(0)
148
- await waitFor(() => {
149
- return screen.getByText('100')
150
- })
151
- expect(MockedComponent).toHaveBeenCalledTimes(1)
152
- expect(MockedComponentAfterSuspense).toHaveBeenCalledTimes(1)
153
- })
154
-
155
- it('should render state', () => {
156
- const appState = create({ count: 0 })
157
- const renderCount = { current: 0 }
158
- // const
159
-
160
- const result = renderHook(() => {
161
- renderCount.current++
162
- return appState()
163
- })
164
- expect(result.result.current).toEqual({ count: 0 })
165
- // count rendered
166
- expect(renderCount.current).toEqual(1)
167
- })
168
-
169
- it('should render state', () => {
170
- const appState = create({ count: 0 })
171
- const slice = appState.select((slice) => slice.count)
172
- const renderCount = { current: 0 }
173
- // const
174
-
175
- const result = renderHook(() => {
176
- renderCount.current++
177
- return slice()
178
- })
179
- expect(result.result.current).toEqual(0)
180
- // count rendered
181
- expect(renderCount.current).toEqual(1)
182
- })
183
-
184
- it('should render state with change', () => {
185
- const appState = create({ count: 0 })
186
- const renderCount = { current: 0 }
187
- // const
188
-
189
- const result = renderHook(() => {
190
- renderCount.current++
191
- return appState((slice) => slice)
192
- })
193
-
194
- act(() => {
195
- appState.setState({ count: 1 })
196
- })
197
- expect(result.result.current).toEqual({ count: 1 })
198
- expect(renderCount.current).toEqual(2)
199
- })
200
-
201
- it('should render state with slice change', () => {
202
- const appState = create({ count: { nested: 0, array: [0] } })
203
- const renderCount = { current: 0 }
204
- const useNestedSlice = appState.select((slice) => slice.count)
205
- const useNestedSliceArray = appState.select((slice) => slice.count.array.length)
206
- const result = renderHook(() => {
207
- return appState()
208
- })
209
- const sliceResult = renderHook(() => {
210
- renderCount.current++
211
- return useNestedSlice()
212
- })
213
- const sliceArrayResult = renderHook(() => {
214
- return useNestedSliceArray()
215
- })
216
- expect(sliceArrayResult.result.current).toEqual(1)
217
- expect(sliceResult.result.current).toEqual({ nested: 0, array: [0] })
218
- act(() => {
219
- appState.setState({ count: { nested: 2, array: [0] } })
220
- })
221
-
222
- expect(result.result.current).toEqual({ count: { nested: 2, array: [0] } })
223
- expect(sliceResult.result.current).toEqual({ nested: 2, array: [0] })
224
-
225
- act(() => {
226
- appState.setState({ count: { nested: 2, array: [1, 2, 4] } })
227
- })
228
- expect(sliceArrayResult.result.current).toEqual(3)
229
- })
230
-
231
- it('should render multiple state', () => {
232
- const mainState = create({ count: { nestedCount: 2 } })
233
- const slice1 = mainState.select((slice) => slice.count)
234
- const slice2FromSlice1 = slice1.select((slice) => slice.nestedCount)
235
-
236
- const slice2FromSlice1Result = renderHook(() => slice2FromSlice1())
237
- expect(slice2FromSlice1Result.result.current).toEqual(2)
238
-
239
- act(() => {
240
- mainState.setState({ count: { nestedCount: 3 } })
241
- })
242
- expect(slice2FromSlice1Result.result.current).toEqual(3)
243
- })
244
-
245
- it('should render multiple state with change', () => {
246
- const appState = create({ count: 0 })
247
- const renderCount1 = { current: 0 }
248
- const renderCount2 = { current: 0 }
249
- // const
250
-
251
- const result1 = renderHook(() => {
252
- renderCount1.current++
253
- return appState()
254
- })
255
- const result2 = renderHook(() => {
256
- renderCount2.current++
257
- return appState((slice) => slice.count)
258
- })
259
- act(() => {
260
- appState.setState({ count: 1 })
261
- })
262
- expect(result1.result.current).toEqual({ count: 1 })
263
- expect(result2.result.current).toEqual(1)
264
- expect(renderCount1.current).toEqual(2)
265
- expect(renderCount2.current).toEqual(2)
266
- })
267
-
268
- it('should test initial state', () => {
269
- const appState = create({ count: 0 })
270
- expect(appState.getState()).toEqual({ count: 0 })
271
- })
272
-
273
- it('should render initial state', () => {
274
- const appState = create({ count: 0 })
275
- const renderCount = { current: 0 }
276
-
277
- const result = renderHook(() => {
278
- renderCount.current++
279
- return appState()
280
- })
281
- expect(result.result.current).toEqual({ count: 0 })
282
- expect(renderCount.current).toEqual(1)
283
- })
284
-
285
- it('should render state after change', () => {
286
- const appState = create({ count: 0 })
287
- const renderCount = { current: 0 }
288
-
289
- const result = renderHook(() => {
290
- renderCount.current++
291
- return appState((slice) => slice)
292
- })
293
-
294
- act(() => {
295
- appState.setState({ count: 1 })
296
- })
297
- expect(result.result.current).toEqual({ count: 1 })
298
- expect(renderCount.current).toEqual(2)
299
- })
300
-
301
- it('should render state with nested slice change', () => {
302
- const appState = create({ count: { nested: 0, array: [0] } })
303
- const renderCount = { current: 0 }
304
- const useNestedSlice = appState.select((slice) => slice.count)
305
- const useNestedSliceArray = appState.select((slice) => slice.count.array.length)
306
-
307
- const result = renderHook(() => appState())
308
- const sliceResult = renderHook(() => {
309
- renderCount.current++
310
- return useNestedSlice()
311
- })
312
- const sliceArrayResult = renderHook(() => useNestedSliceArray())
313
-
314
- expect(sliceArrayResult.result.current).toEqual(1)
315
- expect(sliceResult.result.current).toEqual({ nested: 0, array: [0] })
316
-
317
- act(() => {
318
- appState.setState({ count: { nested: 2, array: [0] } })
319
- })
320
- expect(result.result.current).toEqual({ count: { nested: 2, array: [0] } })
321
- expect(sliceResult.result.current).toEqual({ nested: 2, array: [0] })
322
-
323
- act(() => {
324
- appState.setState({ count: { nested: 2, array: [1, 2, 4] } })
325
- })
326
- expect(sliceArrayResult.result.current).toEqual(3)
327
- })
328
-
329
- it('should render multiple state slices with updates', () => {
330
- const mainState = create({ count: { nestedCount: 2 } })
331
- const slice1 = mainState.select((slice) => slice.count)
332
- const slice2FromSlice1 = slice1.select((slice) => slice.nestedCount)
333
-
334
- const slice2FromSlice1Result = renderHook(() => slice2FromSlice1())
335
- expect(slice2FromSlice1Result.result.current).toEqual(2)
336
-
337
- act(() => {
338
- mainState.setState({ count: { nestedCount: 3 } })
339
- })
340
- expect(slice2FromSlice1Result.result.current).toEqual(3)
341
- })
342
-
343
- it('should render multiple components observing the same state', () => {
344
- const appState = create({ count: 0 })
345
- const renderCount1 = { current: 0 }
346
- const renderCount2 = { current: 0 }
347
-
348
- const result1 = renderHook(() => {
349
- renderCount1.current++
350
- return appState()
351
- })
352
- const result2 = renderHook(() => {
353
- renderCount2.current++
354
- return appState((slice) => slice.count)
355
- })
356
-
357
- act(() => {
358
- appState.setState({ count: 1 })
359
- })
360
- expect(result1.result.current).toEqual({ count: 1 })
361
- expect(result2.result.current).toEqual(1)
362
- expect(renderCount1.current).toEqual(2)
363
- expect(renderCount2.current).toEqual(2)
364
- })
365
-
366
- it('should reset state to default value', () => {
367
- const appState = create({ count: 0 })
368
- act(() => {
369
- appState.setState({ count: 10 })
370
- })
371
- expect(appState.getState()).toEqual({ count: 10 })
372
-
373
- act(() => {
374
- appState.reset()
375
- })
376
- expect(appState.getState()).toEqual({ count: 0 })
377
- })
378
-
379
- it('should handle updates with deep nesting in state', () => {
380
- const appState = create({ data: { nested: { value: 1 } } })
381
- const nestedSlice = appState.select((s) => s.data.nested.value)
382
-
383
- const result = renderHook(() => nestedSlice())
384
- expect(result.result.current).toEqual(1)
385
-
386
- act(() => {
387
- appState.setState({ data: { nested: { value: 2 } } })
388
- })
389
- expect(result.result.current).toEqual(2)
390
- })
391
-
392
- it('should not re-render for unrelated slice changes', () => {
393
- const appState = create({ count: 0, unrelated: 5 })
394
- const renderCount = { current: 0 }
395
-
396
- const countSlice = appState.select((state) => state.count)
397
- const unrelatedSlice = appState.select((state) => state.unrelated)
398
-
399
- renderHook(() => {
400
- renderCount.current++
401
- return countSlice()
402
- })
403
-
404
- const unrelatedResult = renderHook(() => unrelatedSlice())
405
- expect(renderCount.current).toEqual(1)
406
-
407
- act(() => {
408
- return appState.setState({ unrelated: 10 } as never)
409
- })
410
-
411
- expect(unrelatedResult.result.current).toEqual(10)
412
- expect(renderCount.current).toEqual(2) // No re-render for count slice
413
- })
414
-
415
- it('should not re-render where isEqual return true on state', () => {
416
- const appState = create({ count: 0 }, () => true)
417
- const renderCount = { current: 0 }
418
-
419
- renderHook(() => {
420
- renderCount.current++
421
- return appState()
422
- })
423
-
424
- act(() => {
425
- appState.setState({ count: 10 })
426
- })
427
-
428
- expect(renderCount.current).toEqual(1)
429
- })
430
-
431
- it('should not re-render where isEqual return true hook slice', () => {
432
- const appState = create({ count: 0 })
433
- const renderCount = { current: 0 }
434
-
435
- renderHook(() => {
436
- renderCount.current++
437
- return appState(
438
- (slice) => slice,
439
- () => true,
440
- )
441
- })
442
-
443
- act(() => {
444
- appState.setState({ count: 10 })
445
- })
446
-
447
- expect(renderCount.current).toEqual(1)
448
- })
449
-
450
- it('should not re-render where isEqual return true on slice', () => {
451
- const appState = create({ count: 0 })
452
- const appStateSlice = appState.select(
453
- (slice) => slice.count,
454
- () => true,
455
- )
456
- const renderCount = { current: 0 }
457
-
458
- renderHook(() => {
459
- renderCount.current++
460
- return appStateSlice()
461
- })
462
-
463
- act(() => {
464
- appState.setState({ count: 10 })
465
- })
466
- expect(renderCount.current).toEqual(1)
467
- })
468
-
469
- it('should not re-render where isEqual return true on nested slice', () => {
470
- const appState = create({ count: { nested: { count: 0 } } })
471
- const appStateSlice = appState.select((slice) => slice.count)
472
- const nestedAppSlice = appStateSlice.select(
473
- (slice) => slice.nested.count,
474
- () => true,
475
- )
476
- const renderCount = { current: 0 }
477
-
478
- renderHook(() => {
479
- renderCount.current++
480
- return nestedAppSlice()
481
- })
482
-
483
- act(() => {
484
- appState.setState({ count: { nested: { count: 10 } } })
485
- })
486
- expect(renderCount.current).toEqual(1)
487
- })
488
-
489
- it('should use slice with new reference', () => {
490
- const useName = create(() => 'John')
491
- const useDifferentName = useName.select(
492
- (name) => ({
493
- name,
494
- }),
495
- shallow,
496
- )
497
- const result = renderHook(() => useDifferentName())
498
- expect(result.result.current).toEqual({ name: 'John' })
499
- act(() => {
500
- useName.setState('Jane')
501
- })
502
- expect(result.result.current).toEqual({ name: 'Jane' })
503
- })
504
- it('should check if subscribe works', () => {
505
- const appState = create({ count: 0 })
506
- let count = 0
507
- const unsubscribe = appState.subscribe((state) => {
508
- expect(state).toEqual({ count })
509
- count++
510
- })
511
-
512
- act(() => {
513
- appState.setState({ count: 1 })
514
- })
515
- expect(count).toEqual(2)
516
-
517
- unsubscribe()
518
- act(() => {
519
- appState.setState({ count: 2 })
520
- })
521
- expect(count).toEqual(2)
522
- })
523
-
524
- it('should handle rapid consecutive state updates', () => {
525
- const appState = create({ count: 0 })
526
- const renderCount = { current: 0 }
527
-
528
- const result = renderHook(() => {
529
- renderCount.current++
530
- return appState()
531
- })
532
-
533
- act(() => {
534
- // batch updates
535
- appState.setState({ count: 1 })
536
- appState.setState({ count: 2 })
537
- appState.setState({ count: 3 })
538
- })
539
-
540
- expect(result.result.current).toEqual({ count: 3 })
541
- expect(renderCount.current).toEqual(2) // it's batch
542
- })
543
-
544
- it('should handle setting state to the same value', () => {
545
- const appState = create({ count: 0 })
546
- const renderCount = { current: 0 }
547
-
548
- const result = renderHook(() => {
549
- renderCount.current++
550
- return appState()
551
- })
552
-
553
- act(() => {
554
- appState.setState((previous) => previous)
555
- })
556
-
557
- expect(result.result.current).toEqual({ count: 0 })
558
- expect(renderCount.current).toEqual(1)
559
- })
560
-
561
- it('should handle setting state with partial updates', () => {
562
- const appState = create({ count: 0, name: 'John' })
563
- const renderCount = { current: 0 }
564
-
565
- const result = renderHook(() => {
566
- renderCount.current++
567
- return appState()
568
- })
569
-
570
- act(() => {
571
- appState.updateState({ count: 1 })
572
- })
573
-
574
- expect(result.result.current).toEqual({ count: 1, name: 'John' })
575
- expect(renderCount.current).toEqual(2)
576
- })
577
-
578
- it('should handle resetting state after multiple updates', () => {
579
- const appState = create({ count: 0 })
580
- const renderCount = { current: 0 }
581
-
582
- const result = renderHook(() => {
583
- renderCount.current++
584
- return appState()
585
- })
586
-
587
- act(() => {
588
- appState.setState({ count: 1 })
589
- appState.setState({ count: 2 })
590
- appState.reset()
591
- })
592
-
593
- expect(result.result.current).toEqual({ count: 0 })
594
- expect(renderCount.current).toEqual(2)
595
- })
596
-
597
- it('should handle concurrent asynchronous state updates', async () => {
598
- const appState = create({ count: 0 })
599
- const renderCount = { current: 0 }
600
-
601
- const result = renderHook(() => {
602
- renderCount.current++
603
- return appState()
604
- })
605
-
606
- act(() => {
607
- // Simulate concurrent asynchronous updates
608
- appState.setState({ count: 1 })
609
- appState.setState({ count: 2 })
610
- appState.setState({ count: 3 })
611
- })
612
-
613
- await waitFor(() => {
614
- expect(result.result.current).toEqual({ count: 3 })
615
- })
616
-
617
- expect(renderCount.current).toBe(2)
618
- })
619
- })
@@ -1,17 +0,0 @@
1
- import { getDefaultValue } from '../types'
2
-
3
- describe('getDefaultValue', () => {
4
- it('should return the value if it is not a function or promise', () => {
5
- expect(getDefaultValue(123)).toBe(123)
6
- })
7
-
8
- it('should return the resolved value if it is a function', () => {
9
- expect(getDefaultValue(() => 123)).toBe(123)
10
- })
11
-
12
- it('should return the promise if it is a promise', () => {
13
- const promise = Promise.resolve(123)
14
- expect(getDefaultValue(promise)).toBe(promise)
15
- expect(getDefaultValue(() => promise)).toBe(promise)
16
- })
17
- })
package/src/common.ts DELETED
@@ -1,60 +0,0 @@
1
- import { useSyncExternalStoreWithSelector as useSync } from 'use-sync-external-store/shim/with-selector'
2
- import type { Emitter } from './create-emitter'
3
- import type { IsEqual } from './types'
4
- import { useDebugValue } from 'react'
5
-
6
- /**
7
- * Todo need to remove this
8
- */
9
- export function toType<T>(object?: unknown): T {
10
- return object as T
11
- }
12
-
13
- export function useSyncExternalStore<T, S>(
14
- emitter: Emitter<T>,
15
- selector: (stateValue: T) => S,
16
- isEqual?: IsEqual<S>,
17
- ): undefined extends S ? T : S {
18
- const value = useSync<T, S>(
19
- emitter.subscribe,
20
- emitter.getSnapshot,
21
- emitter.getSnapshot,
22
- selector ? (stateValue) => selector(stateValue) : toType,
23
- isEqual,
24
- ) as undefined extends S ? T : S
25
-
26
- useDebugValue(value)
27
- return value
28
- }
29
- // eslint-disable-next-line no-shadow
30
- export enum Abort {
31
- Error = 'StateAbortError',
32
- }
33
- /**
34
- * Cancelable promise function, return promise and controller
35
- */
36
- export function cancelablePromise<T>(
37
- promise: Promise<T>,
38
- previousController?: AbortController,
39
- ): {
40
- promise: Promise<T>
41
- controller: AbortController
42
- } {
43
- if (previousController) {
44
- previousController.abort()
45
- }
46
- const controller = new AbortController()
47
- const { signal } = controller
48
-
49
- const cancelable = new Promise<T>((resolve, reject) => {
50
- // Listen for the abort event
51
- signal.addEventListener('abort', () => {
52
- reject(new DOMException('Promise was aborted', Abort.Error))
53
- })
54
-
55
- // When the original promise settles, resolve or reject accordingly
56
- promise.then(resolve).catch(reject)
57
- })
58
-
59
- return { promise: cancelable, controller }
60
- }