rfcs icon indicating copy to clipboard operation
rfcs copied to clipboard

useEffect status RFC

Open sag1v opened this issue 4 years ago • 5 comments

A status parameter for useEffect/useLayoutEffect callbacks.

There are some discussions in #137

View formatted RFC

sag1v avatar Aug 25 '21 20:08 sag1v

Instead of a custom status object, what about passing an AbortSignal from the new AbortController API.

It's in every modern browser and even Node.js as of v15/v14.17.0.

The code is relatively the same:

useEffect(signal => {
  asyncOp(arg).then(res => {
    !signal.aborted && setState(res);
  });
}, [arg]);

Except as a bonus you get other advantages of the AbortSignal:

  • You can use the signal's signal.throwIfAborted() instead of just signal.aborted
  • You can pass the signal directly to fetch() and get abort on cleanup behaviour without any extra code
  • As AbortSignal is part of the platform and spreading, other libraries will likely start adopting AbortSignal and when they do manual cleanup code can be replaced with just passing the standard AbortSignal to them

dantman avatar Mar 01 '22 23:03 dantman

Interesting idea indeed. Thanks

sag1v avatar Mar 02 '22 06:03 sag1v

  • As AbortSignal is part of the platform and spreading, other libraries will likely start adopting AbortSignal and when they do manual cleanup code can be replaced with just passing the standard AbortSignal to them

😅 Actually, I think I underestimated the spread of this feature. Apparently Chrome 88 already supports AbortSignal on addEventListener.

https://css-tricks.com/using-abortcontroller-as-an-alternative-for-removing-event-listeners/

i.e. This code:

useEffect(() => {
  function paste(e) {
    console.log('Pasted', e);
  }
  window.addEventListener('paste', paste);

  return () => {
    window.removeEventListener('paste', paste);
  };
}, []);

If status was actually an AbortSignal, could be replaced with the following at least for browsers that support it (hopefully there's a polyfill).

useEffect((signal) => {
  function paste(e) {
    console.log('Pasted', e);
  }
  window.addEventListener('paste', paste, { signal });
}, []);

dantman avatar Mar 02 '22 07:03 dantman

Could you clarify where this differs from https://github.com/reactjs/rfcs/pull/204?

eps1lon avatar Mar 02 '22 07:03 eps1lon

Looks like #204 includes the following in addition to the AbortSignal arg:

Accept generator functions so that React can take charge of how async things runs inside the effect.

Which IMHO is enough reason to keep this one around even if this one switches to AbortSignal too. Cause that kind of change is highly likely to stop the RFC from moving on.

dantman avatar Mar 02 '22 18:03 dantman