-
Notifications
You must be signed in to change notification settings - Fork 1
/
useLinkedSignal.ts
46 lines (41 loc) · 1.07 KB
/
useLinkedSignal.ts
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
import {
ReadonlySignal,
Signal,
useSignal,
} from "@preact-signals/unified-signals";
import { useComputedOnce } from "./useComputedOnce";
export type UnwrapSignalDeep<T> = T extends ReadonlySignal<infer V>
? UnwrapSignalDeep<V>
: T;
const unwrap = <T>(value: T): UnwrapSignalDeep<T> =>
value instanceof Signal ? unwrap(value.value) : value;
/**
*
* @example
* ```tsx
* // always linked to value passed to hook
* const s1 = useLinkedSignal(Math.random() > 0.5 ? 1 : 0)
* // 0 | 1
* console.log(s1.peek())
*
* const s2 = useLinkedSignal(Math.random() > 0.5 ? signal(true): false)
* // false | true
* console.log(s2.peek())
*
* // deeply unwrapping
* const s3 = useLinkedSignal(signal(signal(signal(false))))
* // false
* console.log(s3.peek())
* ```
* @param value value that will be unwrapped and linked to result
* @returns
*/
export const useLinkedSignal = <T>(
value: T
): ReadonlySignal<UnwrapSignalDeep<T>> => {
const sig = useSignal(value);
if (sig.peek() !== value) {
sig.value = value;
}
return useComputedOnce(() => unwrap(sig.value));
};