useStableHandler (only use when you know what you are doing, or you will be fired)
A userland implementation of React 18.3 useEffectEvent with the returned function memoized.
Rules
⚠️
Failed to comply will result in you being fired, literally.
The hook IS ONLY FOR:
- Passing event handlers that does not use
useEffectand do not change the state.- For exmaple, you are triggering a metric report with an
onClickhandler that also reports the current state/prop (which won’t change the state). - The passed event handler must not be fired inside
useEffect, which you should use React’suseEffectEventinstead. - https://react.dev/learn/reusing-logic-with-custom-hooks#passing-event-handlers-to-custom-hooks
- For exmaple, you are triggering a metric report with an
The hook IS NOT FOR:
- Replacing the
useCallback - Replacing the
useEffectEvent - Updating state in response to an event
- You can always use
useReducerw/ inline reducer to avoid adding current state touseCallback’s dependencies array - See Why
useReducerIs the Cheat Mode of Hooks - Also see
sukkaw/foxact @ 5934ed8for an example, where I drop theuseStableHandlerfrom foxact’suseUncontrolled. - In short, reducer is inlined inside the component, thus having access to the latest prop/state when dispatched.
- You can always use
- Memoizing selector function of global state management libraries
- Use
useSyncExternalStoreWithSelectorinstead - https://github.com/reactwg/react-18/discussions/86
- Use
- Separating Events Handler from Effects
- Use React’s
useEffectEventinstead - https://react.dev/learn/separating-events-from-effects#declaring-an-effect-event
- Use React’s
Difference with React’s useEffectEvent
useEffectEventis implemented in React, whileuseStableHandleris implemented in userland.- The returned function of
useStableHandleris always memoized, while the return value ofuseEffectEventis guaranteed to not be memoized at all - The returned function of
useEffectEventcan not be called during the render phase.- Although the returned function
useStableHandlershould not be called during the render phase as well, it is implemented in a way to only prevent invocation during the render phase before the first mount. - You will also be fired if you try to exploit this implementation detail.
- Although the returned function
When you don’t need useStableHandler
You don’t necessarily need useStableHandler if you are just updating a state based on other states or current props.
See this GitHub commit sukkaw/foxact @ 5934ed8 for an example, where I drop the useStableHandler from foxact’s useUncontrolled.
Usage
import { useStableHandler } from 'foxact/use-stable-handler-only-when-you-know-what-you-are-doing-or-you-will-be-fired';The detailed usage and the example are intentionally redacted.