reactjs / react.dev

The React documentation website
https://react.dev/
Creative Commons Attribution 4.0 International
11.07k stars 7.55k forks source link

Some recommended alternatives to useEffect are less declarative and concise #7012

Open jedwards1211 opened 4 months ago

jedwards1211 commented 4 months ago

Summary

You Might Not Need an Effect has this example:

  // 🔴 Avoid: Adjusting state on prop change in an Effect
  useEffect(() => {
    setSelection(null);
  }, [items]);

I understand the technical reasons for discouraging useEffect, but it seems like the authors haven't considered this from a readability perspective.

The docs suggest this instead, which is way less concise, declarative, and IMO much less readable:

  // Better: Adjust the state while rendering
  const [prevItems, setPrevItems] = useState(items);
  if (items !== prevItems) {
    setPrevItems(items);
    setSelection(null);
  }

Page

https://react.dev/learn/you-might-not-need-an-effect#adjusting-some-state-when-a-prop-changes

Details

To have the better readability, I would use this custom hook in userland. Since it's so easy for people to abuse useEffect, I would argue React should provide something like the following as a builtin. But if not, the docs should at least recommend it:

useImmediateEffect(() => {
  setSelection(null);
}, [items]);
function useImmediateEffect(effect, deps) {
  const [finishLastEffect, setFinishLastEffect] = useState(() => {});
  const [prevDeps, setPrevDeps] = useState(deps);
  if (!shallowEqual(deps, prevDeps)) {
    setPrevDeps(deps);
    finishLastEffect();
    setFinishLastEffect(effect());
  }
}