macyou
macyou

Reputation: 109

Why React render 3 times rather than 2 after setInterval?

As the function body of React function component is like the render function of the React class component, the React function component should be executed repeatedly whenever it's rendered. So I wrote below code to verify this behavior.

import { useEffect, useState } from "react";
import "./styles.css";
let i = 0;
export default function App() {
  console.log("App:", ++i);
  const [count, setCount] = useState(0);
  useEffect(() => {
    setInterval(() => setCount(count + 1), 2000);
  }, []);

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Count:{count}</h2>
    </div>
  );
}

I expect the console output as below:

App: 1
App: 2

But the actual result is as below:

App: 1
App: 3
App: 5

Please check:Example code in codesandbox

My understanding is that, i should be 1 when App component is executed for the first time. After 2 seconds, setCount(0+1) update count from 0 to 1, React triggers a re-rendering which run App function for the second time, and should print "App: 2" in console. Every 2 seconds after that, setCount(0+1) will be executed repeatedly without triggering any count update as count is always 1 after that.
But the actual result is totally different from my expectation.
Very appreciate if anyone could help correcting my misunderstanding.

Upvotes: 1

Views: 507

Answers (1)

AKX
AKX

Reputation: 168996

How many times your component function is called doesn't matter and shouldn't matter for your app.

React is absolutely free to call your component function a thousand times per update if it feels like it (and indeed, in strict mode it does so twice); that's why you're supposed to make them idempotent and to use React.useMemo if you have heavy computations.

However, your component is broken in that the effect doesn't capture count, so the count may not correctly increase. (The rules of hooks ESlint rules will let you know.) You'd want the function form of setState to derive the new state from the old one:

setCount(count => count + 1);

Upvotes: 1

Related Questions