skip to Main Content

I have a very simple React app to better understand how useEffect works.
This app has the App component with useEffect hook. Inside this hook, I simulate a heavy synchronous task using a for loop.
I am curious about the reasons behind the differing rendering outcomes when I place the for loop inside or outside the if condition.

import { useState, useEffect } from "react";

function App() {
  const [value, setValue] = useState(0);

  useEffect(() => {
    for (let index = 0; index < 1e9; index++) {}
    if (value === 0) {
      // or inside
      // for (let index = 0; index < 1e9; index++) {}
      setValue(Math.random());
    }
  }, [value]);

  return (
    <div>
      value: {value}
      <div>
        <button onClick={() => setValue(0)}>UseEffect</button>
      </div>
    </div>
  );
}

export default App;

Here is my code: https://codesandbox.io/s/useeffect-3zkw27

When I place for loop outside if condition:

enter image description here

When I place for loop inside if condition:

enter image description here

You can see that rendered value changes much faster when the loop is inside if condition. Any ideas why?

UPDATE. Ok, I have decided to change my code a bit in order to run for loop only once. Let’s say I have for loop either inside if or inside else. Again, I have visually different behaviour… So I am closer to understand the behaviour, but still it is not clear.

useEffect(() => {
if (value === 0) {
  // for (let index = 0; index < 1e9; index++) {}
  setValue(Math.random());
} else {
  for (let index = 0; index < 1e9; index++) {}
}

}, [value]);

2

Answers


  1. Chosen as BEST ANSWER

    Eventually, I changed my code to have just one execution of a for loop. Now, I have a better understanding of what's happening.

    You can find the results of my 'study' here:

    https://github.com/esinmy/useEffect-vs-useLayoutEffect


  2. I would probably use logs without <StrictMode> to understand this better:

    import { useState, useEffect } from "react";
    
    let nRender = -1;
    let nEffect = -1;
    
    function App() {
      const [value, setValue] = useState(0);
      console.log(`Render@${++nRender} with `value`: ${value}`);
    
      useEffect(() => {
        console.log(`Render@${nRender} -> Effect@${++nEffect}`);
        // console.log(`Render@${nRender} -> Effect@${nEffect} -> Delaying`);
        // for (let index = 0; index < 1e9; index++) {}
        if (value === 0) {
          console.log(
            `Render@${nRender} -> Effect@${nEffect} -> Delaying because `value === 0``
          );
          for (let index = 0; index < 1e9; index++) {}
    
          const newValue = Math.random();
          console.log(
            `Render@${nRender} -> Effect@${nEffect} -> Setting `value = ${newValue}``
          );
          setValue(newValue);
        }
      }, [value]);
    
      return (
        <div>
          value: {value}
          <div>
            <button onClick={() => (console.log("Click"), setValue(0))}>
              UseEffect
            </button>
          </div>
        </div>
      );
    }
    
    export default App;
    

    Outside of the if statement:

    for outside of the if

    Inside the if statement:

    for inside the if

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search