UNPKG

@multisynq/react

Version:

React bindings for Multisynq

50 lines (49 loc) 1.92 kB
import { useCallback } from 'react'; import { useView } from './useView'; /** Hook that returns a function that will have an event publishing effect. * Needs to be provided with a `publishCallback` that determines the event and data to be published, * by either returning `[scope, event, data]` or just `[scope, event]`. * Any arguments passed to the function returned by the hook will be forwarded to `publishCallback` as-is. * Make sure that the callback function captures all its dependencies by creating one with useCallback, or pass a fresh function. * * The hook is parameterized by the type of data it publishes. * You can provide the same type for usePublish and subscribe on the model side to ensure the types are consistent. * * A simple example: * ``` * function IncrementCounterButton({counterModel}) { * const publishIncrement = usePublish<number>( * () => [counterModel.id, 'increment', 1] * ) * * return <button onClick={publishIncrement} value='Increment'/> * } * ``` * * Forwarding arguments: * ``` * function IncrementCounterBy10Button({counterModel}) { * const publishIncrement = usePublish<number>( * (incrementBy) => [counterModel.id, 'increment', incrementBy]) * * return <button onClick={() => publishIncrement(10)} value='Increment by 10'/> * } * ``` */ export function usePublish(publishCallback) { const multisynqView = useView(); return useCallback((...args) => { if (multisynqView === null) return; const result = publishCallback(...args); let ret; if (result && result.length >= 2) { const [scope, event, data] = result; multisynqView.publish(scope, event, data); ret = data; } return ret; }, // deps are not in play here as publishCallback has to be fresh to capture what it depends on [publishCallback, multisynqView]); }