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 | 1x 1x 1x 1x 1x 1x 6x 6x 6x 6x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 6x 6x 6x 6x 6x 6x 4x 6x 6x 6x 6x 6x | import { binding, captureStack, type ObjLike } from '@anchorlib/core';
import { useMicrotask } from './hooks.js';
import { CLEANUP_DEBOUNCE_TIME } from './constant.js';
import { useEffect } from 'react';
import { getRefState } from './ref.js';
import type { BindingLink, BindingParam } from './types.js';
/**
* A React hook that creates a binding between a property of a reactive object and another value.
*
* This hook establishes a connection between a property in a reactive state object and a binding source,
* allowing automatic synchronization of values. The binding is automatically cleaned up when the component
* unmounts or when the dependencies change.
*
* @template S - The type of the reactive state object
* @template T - The type of the binding source object
* @template B - The type of the key in the binding source object
*
* @param state - The reactive state object whose property will be bound
* @param key - The key of the property in the state object to bind
* @param bind - A tuple containing the binding source object and key, or undefined to skip binding
*
* @returns The same state object with the specified property now bound to the provided source
* @throws {Error} When attempting to bind to a constant value, as constants cannot be modified after creation
*/
export function useBinding<S extends ObjLike, T, B>(state: S, key: keyof S, bind?: BindingParam<T, B>): S {
const [cleanup, cancelCleanup] = useMicrotask(CLEANUP_DEBOUNCE_TIME);
const [bindObj, bindKey] = (Array.isArray(bind) ? bind : [bind]) as BindingLink<T, B>;
const bindRef = getRefState(bindObj);
if (bindRef?.constant) {
const error = new Error('Binding to constant is not allowed.');
captureStack.violation.general(
'Binding violation detected:',
'Attempted to bind to a constant.',
error,
[
'Constant value cannot be changed after created.',
'- Constant only updated when its dependency changed.',
'- Use variable if you need to update its value later.',
],
useBinding
);
}
const unbind =
bindRef && !bindRef.constant ? binding((bindKey ? [bindObj, bindKey] : bindRef) as never, state, key) : undefined;
useEffect(() => {
cancelCleanup();
return () => {
cleanup(() => {
unbind?.();
});
};
}, [unbind]);
return state;
}
|