@effect/atom-react 4.0.0-beta.8 → 4.0.0-beta.81
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/dist/Hooks.d.ts +214 -13
- package/dist/Hooks.d.ts.map +1 -1
- package/dist/Hooks.js +186 -12
- package/dist/Hooks.js.map +1 -1
- package/dist/ReactHydration.d.ts +22 -2
- package/dist/ReactHydration.d.ts.map +1 -1
- package/dist/ReactHydration.js +25 -2
- package/dist/ReactHydration.js.map +1 -1
- package/dist/RegistryContext.d.ts +40 -3
- package/dist/RegistryContext.d.ts.map +1 -1
- package/dist/RegistryContext.js +46 -4
- package/dist/RegistryContext.js.map +1 -1
- package/dist/ScopedAtom.d.ts +49 -23
- package/dist/ScopedAtom.d.ts.map +1 -1
- package/dist/ScopedAtom.js +38 -12
- package/dist/ScopedAtom.js.map +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.js +5 -5
- package/package.json +9 -9
- package/src/Hooks.ts +220 -14
- package/src/ReactHydration.ts +29 -3
- package/src/RegistryContext.ts +46 -4
- package/src/ScopedAtom.ts +55 -24
- package/src/index.ts +5 -5
package/src/Hooks.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* React hooks for working with Effect atoms from components. The hooks read,
|
|
3
|
+
* write, mount, refresh, and subscribe to atoms from `RegistryContext`, handle
|
|
4
|
+
* `AsyncResult` atoms with React Suspense, and expose helpers for reading and
|
|
5
|
+
* deriving `AtomRef` values.
|
|
6
|
+
*
|
|
7
|
+
* @since 4.0.0
|
|
3
8
|
*/
|
|
4
9
|
"use client"
|
|
5
10
|
|
|
@@ -55,8 +60,20 @@ function useStore<A>(registry: AtomRegistry.AtomRegistry, atom: Atom.Atom<A>): A
|
|
|
55
60
|
const initialValuesSet = new WeakMap<AtomRegistry.AtomRegistry, WeakSet<Atom.Atom<any>>>()
|
|
56
61
|
|
|
57
62
|
/**
|
|
58
|
-
*
|
|
63
|
+
* Seeds initial atom values in the current React atom registry.
|
|
64
|
+
*
|
|
65
|
+
* **When to use**
|
|
66
|
+
*
|
|
67
|
+
* Use to seed atom values from a React component after the current registry
|
|
68
|
+
* already exists.
|
|
69
|
+
*
|
|
70
|
+
* **Gotchas**
|
|
71
|
+
*
|
|
72
|
+
* Each atom is initialized at most once for a given registry by this hook, so
|
|
73
|
+
* later calls for the same atom in that registry are ignored.
|
|
74
|
+
*
|
|
59
75
|
* @category hooks
|
|
76
|
+
* @since 4.0.0
|
|
60
77
|
*/
|
|
61
78
|
export const useAtomInitialValues = (initialValues: Iterable<readonly [Atom.Atom<any>, any]>): void => {
|
|
62
79
|
const registry = React.useContext(RegistryContext)
|
|
@@ -74,18 +91,66 @@ export const useAtomInitialValues = (initialValues: Iterable<readonly [Atom.Atom
|
|
|
74
91
|
}
|
|
75
92
|
|
|
76
93
|
/**
|
|
77
|
-
*
|
|
94
|
+
* Subscribes to an atom in the current React registry and returns its current
|
|
95
|
+
* value, optionally mapped through a selector.
|
|
96
|
+
*
|
|
97
|
+
* **When to use**
|
|
98
|
+
*
|
|
99
|
+
* Use when a React component needs to render from an atom value without also
|
|
100
|
+
* returning a setter.
|
|
101
|
+
*
|
|
102
|
+
* **Details**
|
|
103
|
+
*
|
|
104
|
+
* When a selector is provided, the hook maps the atom before subscribing so the
|
|
105
|
+
* component reads the selected value from the current `RegistryContext`.
|
|
106
|
+
*
|
|
107
|
+
* @see {@link useAtom} for reading and updating a writable atom from one component
|
|
108
|
+
* @see {@link useAtomRef} for reading an `AtomRef` directly
|
|
109
|
+
*
|
|
78
110
|
* @category hooks
|
|
111
|
+
* @since 4.0.0
|
|
79
112
|
*/
|
|
80
113
|
export const useAtomValue: {
|
|
81
114
|
/**
|
|
82
|
-
*
|
|
115
|
+
* Subscribes to an atom in the current React registry and returns its current
|
|
116
|
+
* value, optionally mapped through a selector.
|
|
117
|
+
*
|
|
118
|
+
* **When to use**
|
|
119
|
+
*
|
|
120
|
+
* Use when a React component needs to render from an atom value without also
|
|
121
|
+
* returning a setter.
|
|
122
|
+
*
|
|
123
|
+
* **Details**
|
|
124
|
+
*
|
|
125
|
+
* When a selector is provided, the hook maps the atom before subscribing so the
|
|
126
|
+
* component reads the selected value from the current `RegistryContext`.
|
|
127
|
+
*
|
|
128
|
+
* @see {@link useAtom} for reading and updating a writable atom from one component
|
|
129
|
+
* @see {@link useAtomRef} for reading an `AtomRef` directly
|
|
130
|
+
*
|
|
83
131
|
* @category hooks
|
|
132
|
+
* @since 4.0.0
|
|
84
133
|
*/
|
|
85
134
|
<A>(atom: Atom.Atom<A>): A
|
|
86
135
|
/**
|
|
87
|
-
*
|
|
136
|
+
* Subscribes to an atom in the current React registry and returns its current
|
|
137
|
+
* value, optionally mapped through a selector.
|
|
138
|
+
*
|
|
139
|
+
* **When to use**
|
|
140
|
+
*
|
|
141
|
+
* Use when a React component needs to render from an atom value without also
|
|
142
|
+
* returning a setter.
|
|
143
|
+
*
|
|
144
|
+
* **Details**
|
|
145
|
+
*
|
|
146
|
+
* When a selector is provided, the hook maps the atom before subscribing so the
|
|
147
|
+
* component reads the selected value from the current `RegistryContext`.
|
|
148
|
+
*
|
|
149
|
+
* @see {@link useAtom} for reading and updating a writable atom from one component
|
|
150
|
+
* @see {@link useAtomRef} for reading an `AtomRef` directly
|
|
151
|
+
*
|
|
88
152
|
* @category hooks
|
|
153
|
+
* @since 4.0.0
|
|
89
154
|
*/
|
|
90
155
|
<A, B>(atom: Atom.Atom<A>, f: (_: A) => B): B
|
|
91
156
|
} = <A>(atom: Atom.Atom<A>, f?: (_: A) => A): A => {
|
|
@@ -137,8 +202,25 @@ const flattenExit = <A, E>(exit: Exit.Exit<A, E>): A => {
|
|
|
137
202
|
}
|
|
138
203
|
|
|
139
204
|
/**
|
|
140
|
-
*
|
|
205
|
+
* Mounts an atom in the current React registry for the lifetime of the
|
|
206
|
+
* component.
|
|
207
|
+
*
|
|
208
|
+
* **When to use**
|
|
209
|
+
*
|
|
210
|
+
* Use to keep an atom mounted from a React component without reading, writing,
|
|
211
|
+
* or refreshing it.
|
|
212
|
+
*
|
|
213
|
+
* **Details**
|
|
214
|
+
*
|
|
215
|
+
* The hook uses the current `RegistryContext` and releases the mount through
|
|
216
|
+
* React effect cleanup when the component unmounts or when the registry or atom
|
|
217
|
+
* dependency changes.
|
|
218
|
+
*
|
|
219
|
+
* @see {@link useAtomSet} for mounting a writable atom while returning a setter
|
|
220
|
+
* @see {@link useAtomRefresh} for mounting an atom while returning a refresh callback
|
|
221
|
+
*
|
|
141
222
|
* @category hooks
|
|
223
|
+
* @since 4.0.0
|
|
142
224
|
*/
|
|
143
225
|
export const useAtomMount = <A>(atom: Atom.Atom<A>): void => {
|
|
144
226
|
const registry = React.useContext(RegistryContext)
|
|
@@ -146,8 +228,23 @@ export const useAtomMount = <A>(atom: Atom.Atom<A>): void => {
|
|
|
146
228
|
}
|
|
147
229
|
|
|
148
230
|
/**
|
|
149
|
-
*
|
|
231
|
+
* Mounts a writable atom and returns a setter without subscribing to its value.
|
|
232
|
+
*
|
|
233
|
+
* **When to use**
|
|
234
|
+
*
|
|
235
|
+
* Use when a React component needs to update a writable atom without rendering
|
|
236
|
+
* from that atom's value.
|
|
237
|
+
*
|
|
238
|
+
* **Details**
|
|
239
|
+
*
|
|
240
|
+
* The hook mounts the atom and returns a setter. In value mode the setter
|
|
241
|
+
* accepts a write value or updater function; for `AsyncResult` atoms, `promise`
|
|
242
|
+
* and `promiseExit` modes return a promise for the success value or full `Exit`.
|
|
243
|
+
*
|
|
244
|
+
* @see {@link useAtom} for reading and updating the same writable atom
|
|
245
|
+
*
|
|
150
246
|
* @category hooks
|
|
247
|
+
* @since 4.0.0
|
|
151
248
|
*/
|
|
152
249
|
export const useAtomSet = <
|
|
153
250
|
R,
|
|
@@ -172,8 +269,23 @@ export const useAtomSet = <
|
|
|
172
269
|
}
|
|
173
270
|
|
|
174
271
|
/**
|
|
175
|
-
*
|
|
272
|
+
* Mounts an atom and returns a callback that refreshes it in the current React
|
|
273
|
+
* registry.
|
|
274
|
+
*
|
|
275
|
+
* **When to use**
|
|
276
|
+
*
|
|
277
|
+
* Use to expose a React callback that requests a refresh for an atom without
|
|
278
|
+
* reading or writing its value.
|
|
279
|
+
*
|
|
280
|
+
* **Details**
|
|
281
|
+
*
|
|
282
|
+
* The hook uses the current `RegistryContext`, mounts the atom for the
|
|
283
|
+
* component lifetime, and returns a callback that calls `registry.refresh`.
|
|
284
|
+
*
|
|
285
|
+
* @see {@link useAtomMount} for mounting an atom without returning a refresh callback
|
|
286
|
+
*
|
|
176
287
|
* @category hooks
|
|
288
|
+
* @since 4.0.0
|
|
177
289
|
*/
|
|
178
290
|
export const useAtomRefresh = <A>(atom: Atom.Atom<A>): () => void => {
|
|
179
291
|
const registry = React.useContext(RegistryContext)
|
|
@@ -184,8 +296,19 @@ export const useAtomRefresh = <A>(atom: Atom.Atom<A>): () => void => {
|
|
|
184
296
|
}
|
|
185
297
|
|
|
186
298
|
/**
|
|
187
|
-
*
|
|
299
|
+
* Subscribes to a writable atom and returns its current value together with a
|
|
300
|
+
* setter for updating it.
|
|
301
|
+
*
|
|
302
|
+
* **When to use**
|
|
303
|
+
*
|
|
304
|
+
* Use when a React component needs both to render the current value of a
|
|
305
|
+
* writable atom and update it from the same component.
|
|
306
|
+
*
|
|
307
|
+
* @see {@link useAtomValue} for subscribing to an atom without a setter
|
|
308
|
+
* @see {@link useAtomSet} for updating a writable atom without subscribing to its value
|
|
309
|
+
*
|
|
188
310
|
* @category hooks
|
|
311
|
+
* @since 4.0.0
|
|
189
312
|
*/
|
|
190
313
|
export const useAtom = <R, W, const Mode extends "value" | "promise" | "promiseExit" = never>(
|
|
191
314
|
atom: Atom.Writable<R, W>,
|
|
@@ -251,8 +374,28 @@ function atomResultOrSuspend<A, E>(
|
|
|
251
374
|
}
|
|
252
375
|
|
|
253
376
|
/**
|
|
254
|
-
*
|
|
377
|
+
* Reads an `AsyncResult` atom through React Suspense, suspending while the
|
|
378
|
+
* result is initial or configured as waiting.
|
|
379
|
+
*
|
|
380
|
+
* **When to use**
|
|
381
|
+
*
|
|
382
|
+
* Use when a React component should render only after an `AsyncResult` atom has
|
|
383
|
+
* left its initial state, with loading delegated to a Suspense boundary.
|
|
384
|
+
*
|
|
385
|
+
* **Details**
|
|
386
|
+
*
|
|
387
|
+
* `suspendOnWaiting` defaults to `false`. When `includeFailure` is `true`, a
|
|
388
|
+
* failure result is returned instead of being thrown.
|
|
389
|
+
*
|
|
390
|
+
* **Gotchas**
|
|
391
|
+
*
|
|
392
|
+
* Without `includeFailure`, failure results are thrown with
|
|
393
|
+
* `Cause.squash(result.cause)`, so callers need an error boundary for failures.
|
|
394
|
+
*
|
|
395
|
+
* @see {@link useAtomValue} for reading the raw `AsyncResult` value without Suspense
|
|
396
|
+
*
|
|
255
397
|
* @category hooks
|
|
398
|
+
* @since 4.0.0
|
|
256
399
|
*/
|
|
257
400
|
export const useAtomSuspense = <A, E, const IncludeFailure extends boolean = false>(
|
|
258
401
|
atom: Atom.Atom<AsyncResult.AsyncResult<A, E>>,
|
|
@@ -270,8 +413,24 @@ export const useAtomSuspense = <A, E, const IncludeFailure extends boolean = fal
|
|
|
270
413
|
}
|
|
271
414
|
|
|
272
415
|
/**
|
|
273
|
-
*
|
|
416
|
+
* Subscribes a callback to an atom in the current React registry for the
|
|
417
|
+
* component lifetime.
|
|
418
|
+
*
|
|
419
|
+
* **When to use**
|
|
420
|
+
*
|
|
421
|
+
* Use when a React component needs to run a callback for atom changes without
|
|
422
|
+
* reading the atom value during render.
|
|
423
|
+
*
|
|
424
|
+
* **Details**
|
|
425
|
+
*
|
|
426
|
+
* The subscription is installed in a React effect and cleaned up on unmount or
|
|
427
|
+
* dependency change. When `options.immediate` is enabled, the callback receives
|
|
428
|
+
* the current value when the effect subscribes.
|
|
429
|
+
*
|
|
430
|
+
* @see {@link useAtomValue} for reading an atom value during render instead of running a callback
|
|
431
|
+
*
|
|
274
432
|
* @category hooks
|
|
433
|
+
* @since 4.0.0
|
|
275
434
|
*/
|
|
276
435
|
export const useAtomSubscribe = <A>(
|
|
277
436
|
atom: Atom.Atom<A>,
|
|
@@ -286,8 +445,23 @@ export const useAtomSubscribe = <A>(
|
|
|
286
445
|
}
|
|
287
446
|
|
|
288
447
|
/**
|
|
289
|
-
*
|
|
448
|
+
* Subscribes to an atom ref and returns its latest value.
|
|
449
|
+
*
|
|
450
|
+
* **When to use**
|
|
451
|
+
*
|
|
452
|
+
* Use when a React component should render from an `AtomRef.ReadonlyRef`
|
|
453
|
+
* directly instead of reading an atom through the current registry.
|
|
454
|
+
*
|
|
455
|
+
* **Details**
|
|
456
|
+
*
|
|
457
|
+
* The hook subscribes with `ref.subscribe`, triggers re-renders through React
|
|
458
|
+
* state, and returns the current `ref.value`.
|
|
459
|
+
*
|
|
460
|
+
* @see {@link useAtomValue} for reading an `Atom` from the current registry
|
|
461
|
+
* @see {@link useAtomRefPropValue} for reading a property ref value
|
|
462
|
+
*
|
|
290
463
|
* @category hooks
|
|
464
|
+
* @since 4.0.0
|
|
291
465
|
*/
|
|
292
466
|
export const useAtomRef = <A>(ref: AtomRef.ReadonlyRef<A>): A => {
|
|
293
467
|
const [, setValue] = React.useState(ref.value)
|
|
@@ -296,15 +470,47 @@ export const useAtomRef = <A>(ref: AtomRef.ReadonlyRef<A>): A => {
|
|
|
296
470
|
}
|
|
297
471
|
|
|
298
472
|
/**
|
|
299
|
-
*
|
|
473
|
+
* Returns a memoized atom ref for a property of another atom ref.
|
|
474
|
+
*
|
|
475
|
+
* **When to use**
|
|
476
|
+
*
|
|
477
|
+
* Use to derive an `AtomRef` for one property of an object-shaped atom ref.
|
|
478
|
+
*
|
|
479
|
+
* **Details**
|
|
480
|
+
*
|
|
481
|
+
* The hook memoizes `ref.prop(prop)` for the `[ref, prop]` dependency pair and
|
|
482
|
+
* returns the property ref so callers can read, set, update, or subscribe to
|
|
483
|
+
* that nested property.
|
|
484
|
+
*
|
|
485
|
+
* @see {@link useAtomRef} for subscribing to an atom ref value
|
|
486
|
+
* @see {@link useAtomRefPropValue} for subscribing directly to a property value
|
|
487
|
+
*
|
|
300
488
|
* @category hooks
|
|
489
|
+
* @since 4.0.0
|
|
301
490
|
*/
|
|
302
491
|
export const useAtomRefProp = <A, K extends keyof A>(ref: AtomRef.AtomRef<A>, prop: K): AtomRef.AtomRef<A[K]> =>
|
|
303
492
|
React.useMemo(() => ref.prop(prop), [ref, prop])
|
|
304
493
|
|
|
305
494
|
/**
|
|
306
|
-
*
|
|
495
|
+
* Subscribes to a property ref derived from an atom ref and returns its current
|
|
496
|
+
* value.
|
|
497
|
+
*
|
|
498
|
+
* **When to use**
|
|
499
|
+
*
|
|
500
|
+
* Use when a React component needs only the current value of one property from
|
|
501
|
+
* an object-shaped `AtomRef`.
|
|
502
|
+
*
|
|
503
|
+
* **Details**
|
|
504
|
+
*
|
|
505
|
+
* The hook composes `useAtomRefProp(ref, prop)` with `useAtomRef`, so the
|
|
506
|
+
* property ref is memoized for the `[ref, prop]` pair and then subscribed
|
|
507
|
+
* through `ref.subscribe`.
|
|
508
|
+
*
|
|
509
|
+
* @see {@link useAtomRefProp} for returning the property ref directly
|
|
510
|
+
* @see {@link useAtomRef} for subscribing to a whole atom ref value
|
|
511
|
+
*
|
|
307
512
|
* @category hooks
|
|
513
|
+
* @since 4.0.0
|
|
308
514
|
*/
|
|
309
515
|
export const useAtomRefPropValue = <A, K extends keyof A>(ref: AtomRef.AtomRef<A>, prop: K): A[K] =>
|
|
310
516
|
useAtomRef(useAtomRefProp(ref, prop))
|
package/src/ReactHydration.ts
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* React helpers for applying dehydrated Effect Atom state to a React subtree.
|
|
3
|
+
* The `HydrationBoundary` component reads the nearest `RegistryContext`,
|
|
4
|
+
* hydrates new Atom values before children render, and delays updates for
|
|
5
|
+
* existing Atom values until after commit so React transitions do not update
|
|
6
|
+
* the current UI too early.
|
|
7
|
+
*
|
|
8
|
+
* @since 4.0.0
|
|
3
9
|
*/
|
|
4
10
|
"use client"
|
|
5
11
|
import * as Hydration from "effect/unstable/reactivity/Hydration"
|
|
@@ -7,8 +13,11 @@ import * as React from "react"
|
|
|
7
13
|
import { RegistryContext } from "./RegistryContext.ts"
|
|
8
14
|
|
|
9
15
|
/**
|
|
10
|
-
*
|
|
16
|
+
* Props for a boundary that applies dehydrated Atom values to the nearest
|
|
17
|
+
* {@link RegistryContext} while rendering its children.
|
|
18
|
+
*
|
|
11
19
|
* @category components
|
|
20
|
+
* @since 4.0.0
|
|
12
21
|
*/
|
|
13
22
|
export interface HydrationBoundaryProps {
|
|
14
23
|
state?: Iterable<Hydration.DehydratedAtom>
|
|
@@ -16,8 +25,25 @@ export interface HydrationBoundaryProps {
|
|
|
16
25
|
}
|
|
17
26
|
|
|
18
27
|
/**
|
|
19
|
-
*
|
|
28
|
+
* Provides a React hydration boundary that loads dehydrated Atom values into
|
|
29
|
+
* the current Atom registry.
|
|
30
|
+
*
|
|
31
|
+
* **When to use**
|
|
32
|
+
*
|
|
33
|
+
* Use to apply dehydrated Atom state to a React subtree that reads from the
|
|
34
|
+
* nearest `RegistryContext`.
|
|
35
|
+
*
|
|
36
|
+
* **Details**
|
|
37
|
+
*
|
|
38
|
+
* New Atom values are hydrated during render so descendants can read them
|
|
39
|
+
* immediately, while values for existing Atoms are deferred until after commit
|
|
40
|
+
* so transition data does not update the current UI before React accepts it.
|
|
41
|
+
*
|
|
42
|
+
* @see {@link Hydration.dehydrate} for producing dehydrated Atom state
|
|
43
|
+
* @see {@link Hydration.hydrate} for lower-level non-React hydration
|
|
44
|
+
*
|
|
20
45
|
* @category components
|
|
46
|
+
* @since 4.0.0
|
|
21
47
|
*/
|
|
22
48
|
export const HydrationBoundary: React.FC<HydrationBoundaryProps> = ({
|
|
23
49
|
children,
|
package/src/RegistryContext.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* React context and provider for the Atom registry used by Effect Atom hooks.
|
|
3
|
+
* The registry stores atom values, schedules update work, and cleans up unused
|
|
4
|
+
* atoms. Sharing one registry through React context lets components in the same
|
|
5
|
+
* subtree read and write the same atom state.
|
|
6
|
+
*
|
|
7
|
+
* @since 4.0.0
|
|
3
8
|
*/
|
|
4
9
|
"use client"
|
|
5
10
|
|
|
@@ -9,8 +14,11 @@ import * as React from "react"
|
|
|
9
14
|
import * as Scheduler from "scheduler"
|
|
10
15
|
|
|
11
16
|
/**
|
|
12
|
-
*
|
|
17
|
+
* Schedules Atom registry work with React's scheduler at low priority and
|
|
18
|
+
* returns a cancellation function for the scheduled task.
|
|
19
|
+
*
|
|
13
20
|
* @category context
|
|
21
|
+
* @since 4.0.0
|
|
14
22
|
*/
|
|
15
23
|
export function scheduleTask(f: () => void): () => void {
|
|
16
24
|
const node = Scheduler.unstable_scheduleCallback(Scheduler.unstable_LowPriority, f)
|
|
@@ -18,8 +26,20 @@ export function scheduleTask(f: () => void): () => void {
|
|
|
18
26
|
}
|
|
19
27
|
|
|
20
28
|
/**
|
|
21
|
-
*
|
|
29
|
+
* Provides a React context that supplies the `AtomRegistry` used by Atom hooks and
|
|
30
|
+
* hydration helpers, defaulting to a standalone registry when no provider is
|
|
31
|
+
* present.
|
|
32
|
+
*
|
|
33
|
+
* **When to use**
|
|
34
|
+
*
|
|
35
|
+
* Use to supply an existing `AtomRegistry` through React context when hooks or
|
|
36
|
+
* hydration helpers need to share registry state that is managed outside
|
|
37
|
+
* `RegistryProvider`.
|
|
38
|
+
*
|
|
39
|
+
* @see {@link RegistryProvider} for creating and providing a registry for a React subtree
|
|
40
|
+
*
|
|
22
41
|
* @category context
|
|
42
|
+
* @since 4.0.0
|
|
23
43
|
*/
|
|
24
44
|
export const RegistryContext = React.createContext<AtomRegistry.AtomRegistry>(AtomRegistry.make({
|
|
25
45
|
scheduleTask,
|
|
@@ -27,8 +47,30 @@ export const RegistryContext = React.createContext<AtomRegistry.AtomRegistry>(At
|
|
|
27
47
|
}))
|
|
28
48
|
|
|
29
49
|
/**
|
|
30
|
-
*
|
|
50
|
+
* Provides a stable `AtomRegistry` to a React subtree, optionally seeding
|
|
51
|
+
* initial atom values and overriding registry scheduling or idle settings.
|
|
52
|
+
*
|
|
53
|
+
* **When to use**
|
|
54
|
+
*
|
|
55
|
+
* Use to scope atom state, scheduling, and idle cleanup to a React subtree.
|
|
56
|
+
*
|
|
57
|
+
* **Details**
|
|
58
|
+
*
|
|
59
|
+
* The provider creates one `AtomRegistry` with `AtomRegistry.make`, passes it
|
|
60
|
+
* through `RegistryContext.Provider`, and forwards `initialValues`,
|
|
61
|
+
* `scheduleTask`, `timeoutResolution`, and `defaultIdleTTL` only when that
|
|
62
|
+
* registry is created.
|
|
63
|
+
*
|
|
64
|
+
* **Gotchas**
|
|
65
|
+
*
|
|
66
|
+
* Option changes after the first render do not rebuild the registry. When the
|
|
67
|
+
* provider unmounts, registry disposal is delayed briefly and canceled if the
|
|
68
|
+
* provider remounts before the timeout fires.
|
|
69
|
+
*
|
|
70
|
+
* @see {@link RegistryContext} for the React context supplied by this provider
|
|
71
|
+
*
|
|
31
72
|
* @category context
|
|
73
|
+
* @since 4.0.0
|
|
32
74
|
*/
|
|
33
75
|
export const RegistryProvider = (options: {
|
|
34
76
|
readonly children?: React.ReactNode | undefined
|
package/src/ScopedAtom.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* React helpers for creating Atom instances that belong to one component
|
|
3
|
+
* subtree. `make` returns a scoped atom with a provider, context, and `use`
|
|
4
|
+
* accessor. Each provider creates its own Atom once, so different subtrees can
|
|
5
|
+
* use the same scoped atom definition without sharing state.
|
|
6
|
+
*
|
|
7
|
+
* @since 4.0.0
|
|
3
8
|
*/
|
|
4
9
|
"use client"
|
|
5
10
|
|
|
@@ -7,35 +12,42 @@ import type * as Atom from "effect/unstable/reactivity/Atom"
|
|
|
7
12
|
import * as React from "react"
|
|
8
13
|
|
|
9
14
|
/**
|
|
10
|
-
*
|
|
11
|
-
* @category Type IDs
|
|
15
|
+
* Literal type used as the `ScopedAtom` type identifier.
|
|
12
16
|
*
|
|
13
|
-
*
|
|
17
|
+
* **Details**
|
|
18
|
+
*
|
|
19
|
+
* Used as the computed property key and marker value stored on `ScopedAtom`
|
|
20
|
+
* objects.
|
|
21
|
+
*
|
|
22
|
+
* @category type IDs
|
|
23
|
+
* @since 4.0.0
|
|
14
24
|
*/
|
|
15
25
|
export type TypeId = "~@effect/atom-react/ScopedAtom"
|
|
16
26
|
|
|
17
27
|
/**
|
|
18
|
-
* @since 1.0.0
|
|
19
|
-
* @category Type IDs
|
|
20
|
-
*
|
|
21
28
|
* Type identifier for ScopedAtom.
|
|
29
|
+
*
|
|
30
|
+
* **Details**
|
|
31
|
+
*
|
|
32
|
+
* Used as the computed property key and marker value stored on `ScopedAtom`
|
|
33
|
+
* objects.
|
|
34
|
+
*
|
|
35
|
+
* @category type IDs
|
|
36
|
+
* @since 4.0.0
|
|
22
37
|
*/
|
|
23
38
|
export const TypeId: TypeId = "~@effect/atom-react/ScopedAtom"
|
|
24
39
|
|
|
25
40
|
/**
|
|
26
|
-
* @since 1.0.0
|
|
27
|
-
* @category models
|
|
28
|
-
*
|
|
29
41
|
* Scoped Atom interface with a provider-backed instance.
|
|
30
42
|
*
|
|
31
|
-
*
|
|
43
|
+
* **Example** (Providing and reading a scoped atom)
|
|
44
|
+
*
|
|
32
45
|
* ```ts
|
|
33
|
-
* import
|
|
46
|
+
* import { make, useAtomValue } from "@effect/atom-react"
|
|
47
|
+
* import { Atom } from "effect/unstable/reactivity"
|
|
34
48
|
* import * as React from "react"
|
|
35
|
-
* import * as ScopedAtom from "@effect/atom-react/ScopedAtom"
|
|
36
|
-
* import { useAtomValue } from "@effect/atom-react"
|
|
37
49
|
*
|
|
38
|
-
* const Counter =
|
|
50
|
+
* const Counter = make(() => Atom.make(0))
|
|
39
51
|
*
|
|
40
52
|
* function View() {
|
|
41
53
|
* const atom = Counter.use()
|
|
@@ -47,29 +59,45 @@ export const TypeId: TypeId = "~@effect/atom-react/ScopedAtom"
|
|
|
47
59
|
* return React.createElement(Counter.Provider, null, React.createElement(View))
|
|
48
60
|
* }
|
|
49
61
|
* ```
|
|
62
|
+
*
|
|
63
|
+
* @category models
|
|
64
|
+
* @since 4.0.0
|
|
50
65
|
*/
|
|
51
66
|
export interface ScopedAtom<A extends Atom.Atom<any>, Input = never> {
|
|
52
67
|
readonly [TypeId]: TypeId
|
|
53
68
|
use(): A
|
|
54
|
-
Provider: Input extends never ? React.FC<{ readonly children?: React.ReactNode | undefined }>
|
|
69
|
+
Provider: [Input] extends [never] ? React.FC<{ readonly children?: React.ReactNode | undefined }>
|
|
55
70
|
: React.FC<{ readonly children?: React.ReactNode | undefined; readonly value: Input }>
|
|
56
71
|
Context: React.Context<A>
|
|
57
72
|
}
|
|
58
73
|
|
|
59
74
|
/**
|
|
60
|
-
* @since 1.0.0
|
|
61
|
-
* @category constructors
|
|
62
|
-
*
|
|
63
75
|
* Creates a ScopedAtom from a factory function.
|
|
64
76
|
*
|
|
65
|
-
*
|
|
77
|
+
* **When to use**
|
|
78
|
+
*
|
|
79
|
+
* Use to create an atom instance that is owned by a React provider and scoped
|
|
80
|
+
* to a component subtree.
|
|
81
|
+
*
|
|
82
|
+
* **Details**
|
|
83
|
+
*
|
|
84
|
+
* The returned scoped atom includes a `Provider`, `Context`, and `use`
|
|
85
|
+
* accessor. The provider creates the atom once for its lifetime, passing the
|
|
86
|
+
* `value` prop to the factory when the scoped atom expects input.
|
|
87
|
+
*
|
|
88
|
+
* **Gotchas**
|
|
89
|
+
*
|
|
90
|
+
* `use` must run under the matching provider. Changing the provider `value`
|
|
91
|
+
* prop after mount does not recreate the atom.
|
|
92
|
+
*
|
|
93
|
+
* **Example** (Creating a scoped atom with input)
|
|
94
|
+
*
|
|
66
95
|
* ```ts
|
|
67
|
-
* import
|
|
96
|
+
* import { make, useAtomValue } from "@effect/atom-react"
|
|
97
|
+
* import { Atom } from "effect/unstable/reactivity"
|
|
68
98
|
* import * as React from "react"
|
|
69
|
-
* import * as ScopedAtom from "@effect/atom-react/ScopedAtom"
|
|
70
|
-
* import { useAtomValue } from "@effect/atom-react"
|
|
71
99
|
*
|
|
72
|
-
* const User =
|
|
100
|
+
* const User = make((name: string) => Atom.make(name))
|
|
73
101
|
*
|
|
74
102
|
* function UserName() {
|
|
75
103
|
* const atom = User.use()
|
|
@@ -85,6 +113,9 @@ export interface ScopedAtom<A extends Atom.Atom<any>, Input = never> {
|
|
|
85
113
|
* )
|
|
86
114
|
* }
|
|
87
115
|
* ```
|
|
116
|
+
*
|
|
117
|
+
* @category constructors
|
|
118
|
+
* @since 4.0.0
|
|
88
119
|
*/
|
|
89
120
|
export const make = <A extends Atom.Atom<any>, Input = never>(
|
|
90
121
|
f: (() => A) | ((input: Input) => A)
|
package/src/index.ts
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @since
|
|
2
|
+
* @since 4.0.0
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
* @since
|
|
6
|
+
* @since 4.0.0
|
|
7
7
|
*/
|
|
8
8
|
export * from "./Hooks.ts"
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
* @since
|
|
11
|
+
* @since 4.0.0
|
|
12
12
|
*/
|
|
13
13
|
export * from "./RegistryContext.ts"
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
|
-
* @since
|
|
16
|
+
* @since 4.0.0
|
|
17
17
|
*/
|
|
18
18
|
export * from "./ReactHydration.ts"
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
|
-
* @since
|
|
21
|
+
* @since 4.0.0
|
|
22
22
|
*/
|
|
23
23
|
export * from "./ScopedAtom.ts"
|