@raresportan/marram 0.2.1 → 0.2.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/package.json +1 -1
- package/src/react/keyed.ts +17 -11
package/package.json
CHANGED
package/src/react/keyed.ts
CHANGED
|
@@ -1,19 +1,25 @@
|
|
|
1
|
-
import { useCallback,
|
|
1
|
+
import { useCallback, useReducer } from "react";
|
|
2
|
+
|
|
3
|
+
type Value<T> = T | ((previous: T) => T);
|
|
2
4
|
|
|
3
5
|
/**
|
|
4
6
|
* State that belongs to a key (a watch's parameters, a file, a document): under another key it reads as `initial`, so
|
|
5
7
|
* nothing shows the last key's value while the new key's loads, not even for the one render an effect resetting it
|
|
6
8
|
* would leave. Set it with the key the value is for, or with an update of that key's value; a late answer for a key
|
|
7
|
-
* that's gone
|
|
9
|
+
* that's gone is dropped, so it can't take the place of the current key's value. A key says only what a value is for:
|
|
10
|
+
* two requests under one key can still answer out of order, so a caller that re-reads puts a version or try in the key.
|
|
8
11
|
*/
|
|
9
|
-
export function useKeyed<T>(key: string, initial: T): [T, (forKey: string, value: T
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
export function useKeyed<T>(key: string, initial: T): [T, (forKey: string, value: Value<T>) => void] {
|
|
13
|
+
// Written inline because React runs a reducer in the render an update lands in: this one sees that render's key, which
|
|
14
|
+
// `set`, called from a promise or a listener, can't know.
|
|
15
|
+
const [held, apply] = useReducer(
|
|
16
|
+
(last: { key: string; value: T }, { forKey, value }: { forKey: string; value: Value<T> }) => {
|
|
17
|
+
if (forKey !== key) return last;
|
|
18
|
+
const previous = last.key === key ? last.value : initial;
|
|
19
|
+
return { key, value: typeof value === "function" ? (value as (previous: T) => T)(previous) : value };
|
|
20
|
+
},
|
|
21
|
+
{ key, value: initial },
|
|
22
|
+
);
|
|
23
|
+
const set = useCallback((forKey: string, value: Value<T>) => apply({ forKey, value }), []);
|
|
18
24
|
return [held.key === key ? held.value : initial, set];
|
|
19
25
|
}
|