4

Even though I have the basics but it seems I'm still struggling, I have this example

const Component = () => {
  const [state, setState] = useState("");
  useEffect(() => {
    console.log("useEffect");
    setState("Nebil");
  }, [state]);

  console.log("component rerender ", state);
};
export default Component;

With the above code I see this output

component rerender
useEffect
component rerender Nebil 
useEffect
component rerender Nebil 

I wonder why the second time useEffect fires, it updates the state and causes a render, I thought that when the value is equal to "Nebil" and we set the state to "Nebil" since it is a string, this will not render the component. can you please explain this to me?

note: I don't use strictmode

nebil
  • 52
  • 9

2 Answers2

3

Well, here and explenation on each console.log

component rerender
The default state is ""

useEffect
useEffect is triggered by the default state ""

component rerender Nebil
In useEffect, the state have been changed to "Nebil"

useEffect
since the state is changed, useEffect is triggered by the state "Nebil"

component "rerender" Nebil
since useEffect have been triggered, the function (Component itself is a function) is executed but, even if you see the console.log output, Virtual DOM will not be updated, since it is the same as before, so no additional render will be triggered. You should try to add the return statment and use a developer tool that higligths in green which part of the DOM is updated, I think React dev tools have something to do so.

Emanuele Scarabattoli
  • 4,103
  • 1
  • 12
  • 21
  • 3
    It does not explain why the last log occurs. If you set state only when state !== 'Nebil', the last render won't occur. That leads to the conclusion the setState with the same value causes render, I don't think it is something specific for the useEffect – Oktay Yuzcan Jun 27 '23 at 09:52
  • even if I put the console.log inside the jsx still see the same input that means the component is rerendering, still didn't get your point sorry – nebil Jun 27 '23 at 10:21
  • Did you checked with the dev tools? There is an option like " Highlight updates when components render.". – Emanuele Scarabattoli Jun 27 '23 at 10:26
  • I don't have the extension, but even if you get infinite render of the component there are no updates, but the component renders infinitely – nebil Jun 27 '23 at 10:31
  • Well, as it is writtend in the question, the component should not render infinitely since the state chenges from the initial one "" to "Nebil". By the way, what is the conrete feature you would like to achieve? Having a real scenario whould help. – Emanuele Scarabattoli Jun 27 '23 at 10:34
3

useEffect is a React Hook that lets you synchronize a component with an external system or in your case you are synchronizing it with your state.

By passing the dependency state to the useEffect, React will compare the state with its previous value. Therefore, because you are setting the state inside the useEffect it will cause the component to re-render because the state change from initial value. Here is what is happening:

  1. initial component render
  2. executing useEffect on inital render
  3. component render again because of setState
  4. executing useEffect because dependency has changed from "" to "Nebila"
  5. now we will not execute useEffect because you are setting the same state value, if you initialize a new object inside the ue you will enter an infinite loop!

Try setting your initial state to "Nebil" useState("Nebil"), the useEffect will only be triggered once on initialRender.

Please make sure to remove strictMode because your components will re-render an extra time to find bugs caused by impure rendering.

I created a sandbox to check the render count https://codesandbox.io/s/long-cookies-s4vjg6?file=/src/App.js

Here are some helpful references:

Charles Semaan
  • 304
  • 2
  • 13
  • can you please exaplain more "5. component render due to dependency change in useEffect" I though the component rerenders only when the state is updated which is not the case – nebil Jun 27 '23 at 10:18
  • You are right, I edited my explanation and created a sandbox for you to check – Charles Semaan Jun 27 '23 at 11:07