Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What happens for an useEffect with no second argument or one equal to null or undefined?

I just wanted to know how useEffect will behave if we pass the second argument as null or undefined in place of the dependencies array. Will it render on every cycle? Or just once? Any leads will be appreciated.

like image 637
Mohit Pandey Avatar asked Oct 29 '25 09:10

Mohit Pandey


2 Answers

If you create an useEffect with no second argument or one equal to undefined or null, yes the callback will get executed on every render. And if you have explicitly typed undefined or null as the second argument, and you have Eslint in your editor you would get this warning:

React Hook useEffect was passed a dependency list that is not an array literal. This means we can't statically verify whether you've passed the correct dependencies. (react-hooks/exhaustive-deps)

That's with no harm to your application in a case like below where you don't mutate a state inside the callback, it will just log "Hello Word" every time there is a render.

export default function App() {
  const [state, setState]= useState(true);
  useEffect(() => {
    console.log("Hello Word");
  });
  return (
    <div>
      <button onClick = {()=>setState(!state)}>Toggle State</button>
    </div>
  );
}

It will cause an infinite loop of renders in cases like below where you mutate a state inside the callback. That's because a state change triggers a render, and the callback gets executed on every render.

export default function App() {
  const [state, setState]= useState(true);
  useEffect(() => {
   setState(!state);
  });
  return (
    <div>
      <button onClick = {()=>setState(!state)}>Toggle State</button>
    </div>
  );
}

And to cover all the use cases, there is the one with an empty dependencies array as the second argument, where the callback gets executed only on the first render:

export default function App() {
  const [state, setState]= useState(true);
  useEffect(() => {
   setState(!state);
  },[]);
  return (
    <div>
      <button onClick = {()=>setState(!state)}>Toggle State</button>
    </div>
  );
}

And finally, the one that calls the callback on the first render and every time some state in the dependencies array changes:

export default function App() {
  const [state, setState]= useState(true);
  useEffect(() => {
   console.log("Hello Word");
   // setState(!state); if you mutate state here, it will cause an infinite loop of renders
  },[state]);
  return (
    <div>
      <button onClick = {()=>setState(!state)}>Toggle State</button>
    </div>
  );
}
like image 135
yousoumar Avatar answered Oct 30 '25 23:10

yousoumar


It will rerender every circle if deps is not defined or is null.

In React source, when the second argument is not defined, deps will be null, updateEffectImpl, will always execute pushEffect, and render every circle :

function updateEffectImpl(fiberFlags, hookFlags, create, deps): void {
  const nextDeps = deps === undefined ? null : deps;

  if (currentHook !== null) {
    // .eg
  }

  // always execute
  hook.memoizedState = pushEffect(
    HookHasEffect | hookFlags,
    create,
    destroy,
    nextDeps,
  );
}
like image 31
wenzi Avatar answered Oct 31 '25 00:10

wenzi



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!