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
useEffect
and do not change the state.- For exmaple, you are triggering a metric report with an
onClick
handler 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'suseEffectEvent
instead. - https://react.dev/learn/reusing-logic-with-custom-hooks#passing-event-handlers-to-custom-hooks (opens in a new tab)
- 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
useReducer
w/ inline reducer to avoid adding current state touseCallback
's dependencies array - See Why
useReducer
Is the Cheat Mode of Hooks (opens in a new tab) - Also see
sukkaw/foxact @ 5934ed8
(opens in a new tab) for an example, where I drop theuseStableHandler
from foxact'suseUncontrolled
.
- You can always use
- Memoizing selector function of global state management libraries
- Use
useSyncExternalStoreWithSelector
instead - https://github.com/reactwg/react-18/discussions/86 (opens in a new tab)
- Use
- Separating Events Handler from Effects
- Use React's
useEffectEvent
instead - https://react.dev/learn/separating-events-from-effects#declaring-an-effect-event (opens in a new tab)
- Use React's
Difference with React's useEffectEvent
useEffectEvent
is implemented in React, whileuseStableHandler
is implemented in userland.- The returned function of
useStableHandler
is always memoized, while the return value ofuseEffectEvent
is guaranteed to not be memoized at all - The returned function of
useEffectEvent
can not be called during the render phase.- Although the returned function
useStableHandler
should 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
(opens in a new tab) 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.