Is this an accurate fill for React's upcoming useEffectEvent
hook? Are there any potential issues with it?
The part I'm not sure about is whether the reference is guaranteed to be updated before the returned function is used for any other effect. I think I'm fine with this as long as I never use the rather esoteric useInsertionEffect
anywhere else in my code, but I wanted to confirm.
function useEffectEvent(callback) { const fnRef = useRef(null) useInsertionEffect(() => { fnRef.current = callback }) return (...args) => { return fnRef.current.apply(null, args) } }
P粉1869047312024-01-07 10:10:29
I don't think the React team has proposed an official polyfill for useEffectEvent
(at least I haven't seen it yet).
Having said that, you can originally use useLayoutEffect in
against the now defunct RFC for useEvent. In an early version of Separating events from effects, Dan Abramov showed an updated version that looked like this (no longer visible in the documentation):
import { useRef, useInsertionEffect, useCallback } from 'react'; // The useEvent API has not yet been added to React, // so this is a temporary shim to make this sandbox work. // You're not expected to write code like this yourself. export function useEvent(fn) { const ref = useRef(null); useInsertionEffect(() => { ref.current = fn; }, [fn]); return useCallback((...args) => { const f = ref.current; return f(...args); }, []); }
This polyfill uses useInsertionEffect
. I believe the reason for this choice is that the insert effect is the first to run (compared to useLayoutEffect
and useEffect
). Therefore, it's very safe to assume that the reference is updated before any other effects run.
Later, the RFC for useEvent
was shelved and useEffectEvent
began shown in the documentation . Nonetheless, since the exposed behavior is the same, the same polyfill can be reused to implement useEffectEvent
.
Please note that with this polyfill, the hook returns a stable function (thanks to useCallback(..., [])
), which may not be necessary but is simpler (just in case ) the consumer incorrectly added the returned function to the effect's dependencies).
I'd like to learn more about the polyfill, which I've already blogged about: Check out the useEvent polyfill in the new React documentation.