Press n or j to go to the next uncovered block, b, p or k for the previous block.
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 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | 1x 1x 1x 2x 1x 1x 1x 62x 40x 40x 40x 62x 62x 62x 62x 62x 62x 62x 62x 62x 62x 62x | import { // eslint-disable-next-line @typescript-eslint/no-unused-vars type Readable, type ReadableLike, type Unwrap, getReadable, } from "@embra/reactivity"; import { useDebugValue, useMemo, useSyncExternalStore } from "react"; export interface UseValue { /** * Accepts a {@link ReadableLike} and returns the latest value. * It only triggers re-rendering when new value emitted from $ (base on {@link Readable.$version} instead of React's `Object.is` comparison). * * @param $ A {@link ReadableLike}. * @returns the value of the {@link ReadableLike} */ <T = any>($: ReadableLike<T>): T; /** * Accepts a {@link ReadableLike} and returns the latest value. * It only triggers re-rendering when new value emitted from $ (base on {@link Readable.$version} instead of React's `Object.is` comparison). * * @param $ A {@link ReadableLike}. * @returns the value of the {@link ReadableLike}, or $ itself if $ is not a {@link ReadableLike} */ <T = any, U = any>($: ReadableLike<T> | U): T | U; } const noop = () => { /* noop */ }; const returnsNoop = () => noop; const defaultArgs = [returnsNoop, returnsNoop as () => any] as const; /** * Accepts a {@link ReadableLike} and returns the latest value. * It only triggers re-rendering when new value emitted from $ (base on {@link Readable.$version} instead of React's `Object.is` comparison). * * @param $ A {@link ReadableLike}. * @returns the value of the {@link ReadableLike}, or $ itself if $ is not a {@link ReadableLike} * * @example * ```tsx * import { useValue } from "@embra/reactivity/react"; * * function App({ count$ }) { * const count = useValue(count$); * return <div>{count}</div>; * } * ``` */ export const useValue: UseValue = <T, U>($?: ReadableLike<T> | U): Unwrap<T> | U => { const args = useMemo(() => { const readable = getReadable($); return ( readable && ([(onChange: () => void) => readable.subscribe(onChange), () => readable.$version, readable] as const) ); }, [$]); const [subscriber, getSnapshot, readable] = args ?? defaultArgs; const version = useSyncExternalStore( subscriber, getSnapshot, // It is safe to use the same value getter for server snapshot since val() can // be initialized with a default value. getSnapshot, ); const value = useMemo(() => (readable ? readable.get() : $), [version, readable, $]); useDebugValue(value); return value; }; |