forked from get-convex/convex-helpers
-
Notifications
You must be signed in to change notification settings - Fork 0
/
useLatestValue.ts
40 lines (36 loc) · 1.19 KB
/
useLatestValue.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
import { useCallback, useMemo, useRef } from 'react';
/**
* Promise-based access to the latest value updated.
* Every call to nextValue will return a promise to the next value.
* "Next value" is defined as the latest value passed to "updateValue" that
* hasn not been returned yet.
* @returns a function to await for a new value, and one to update the value.
*/
export default function useLatestValue<T>() {
const initial = useMemo(() => {
const [promise, resolve] = makeSignal();
// We won't access data until it has been updated.
return { data: undefined as T, promise, resolve };
}, []);
const ref = useRef(initial);
const nextValue = useCallback(async () => {
await ref.current.promise;
const [promise, resolve] = makeSignal();
ref.current.promise = promise;
ref.current.resolve = resolve;
return ref.current.data;
}, [ref]);
const updateValue = useCallback(
(data: T) => {
ref.current.data = data;
ref.current.resolve();
},
[ref]
);
return [nextValue, updateValue] as const;
}
const makeSignal = () => {
let resolve: () => void;
const promise = new Promise<void>((r) => (resolve = r));
return [promise, resolve!] as const;
};