Propagates a value to multiple nodes via callback function using React context and hooks.
This pattern is useful for triggering multiple nodes via callback function.
Unlike setting a value in a context, invoking a callback function will not trigger re-render. Subscribers can choose to save the value into its state and re-render as needed.
The following code snippet sends the focus to the text box when the button is tapped.
import { createPropagation } from 'use-propagate';
// Creates a namespace for the propagation. This should be placed outside of the component.
const { useListen, usePropagate } = createPropagation<void>();
const FocusButton = () => {
const propagate = usePropagate();
// When tapped, it will trigger all subscribers.
const handleClick = useCallback(() => propagate(), [propagate]);
return (
<button autoFocus={true} onClick={handleClick}>
Tap to focus to the text box
</button>
);
};
const TextBox = () => {
const ref = useRef<HTMLInputElement>(null);
// When the callback is called, send the focus to the text box.
const handleListen = useCallback(() => ref.current?.focus(), [ref]);
// Listens to the propagation.
useListen(handleListen);
return <input ref={ref} type="text" />;
};
render(
<Fragment>
<FocusButton />
<TextBox />
</Fragment>
);
export function createPropagation<T>(): {
useListen: (callback: (value: T) => void) => void;
usePropagate: (value: T) => void;
};
When propagating a value via useContext
, subscribing nodes will be re-rendered. This behavior may not be desirable for events and certain type of scenarios.
When the propagate callback function is called during rendering, a warning message will be printed and propagation will be stopped.
This is a safety measure to prevent multiple re-render and potential deadlock situation if listeners save the value to a state and trigger another re-render.
If listeners are controlled and would never trigger re-render, you can pass allowPropagateDuringRender: true
option to ignore this safety measure.
Modifies the passing value by following the FetchEvent.respondWith
or ExtendableEvent.waitUntil
pattern.
Use the following code snippet to save the value to a state, which will re-render the component.
const MyComponent = () => {
const [value, setValue] = useState<number>();
// When triggered, saves the value to state.
useListen(setValue);
return <p>The value is {value}.</p>;
};
Please make sure the propagate callback function is not called during render as it could cause multiple re-render and potential deadlock situation.
Like us? Star us.
Want to make it better? File us an issue.
Don't like something you see? Submit a pull request.