Is this an accurate polyfill of react's upcoming useEffectEvent hook? Does it present any potential issues?
One part I was not sure about was whether the ref is guaranteed to have been updated prior to the returned function being used in any other effects. I think I'm okay on this front so long as I never use the rather esoteric useInsertionEffect anywhere else in my code, but I would like to confirm that.
function useEffectEvent(callback) {
const fnRef = useRef(null)
useInsertionEffect(() => {
fnRef.current = callback
})
return (...args) => {
return fnRef.current.apply(null, args)
}
}
I don't think the React team has proposed an official polyfill for useEffectEvent (at least I haven't seen it).
Having said that, you can see a polyfill inside the RFC for the now defunct useEvent which initially used useLayoutEffect. And in an early version of Separating Events from Effects, Dan Abramov showed an updated version that looked like this (no longer visible in the docs):
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 that the reason for this choice is that insertion effects are the first to run (compared with useLayoutEffect and useEffect). So it is pretty safe to assume that the ref is updated before any of your other effects run.
Later on, the RFC for useEvent was shelved and useEffectEvent started to show in the docs. Nonetheless, the same polyfill can be reused to implement useEffectEvent since the exposed behaviour is the same.
Please note that with this polyfill, the hook returns a stable function (thanks to useCallback(..., [])), which might not be necessary but is more fool proof (in case the consumer adds the returned function to the dependencies of the effect by mistake).
If you want to understand more about the polyfill, I've blogged about it in: A look inside the useEvent polyfill from the new React docs.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With