Home > front end >  how many time React should render
how many time React should render

Time:11-25

I wrote a simple react to test how React render:

    import ReactDOM from 'react-dom';
    import React, { useState, useEffect } from 'react';
    const App = (props) => {
      // State
      const [trackIndex, setTrackIndex] = useState(1);
      const [trackProgress, setTrackProgress] = useState(0);
      const clickHandler = () =>{
           setTrackIndex((trackIndex)=>trackIndex 1)
      }
 
      useEffect(() => {
        console.log("effect; trackIndex=",trackIndex)
        console.log("effect; trackProgress=",trackProgress)
        if(trackIndex<5){
          console.log("set trackProgress")
          setTrackProgress(trackIndex)
        }
      });
      console.log("render")
      return (
        <div>
          <p>{trackIndex}</p>
          <p>{trackProgress}</p>
          <button onClick={clickHandler}>Click me</button>
        </div>
      );
    };

ReactDOM.render(
      <App />,
  document.getElementById('root')
);

The following is the console output:

render
effect; trackIndex= 1
effect; trackProgress= 0
set trackProgress
render
effect; trackIndex= 1
effect; trackProgress= 1
set trackProgress
render

It seems that React renders three times before I click the button. The last rendering really confuses me. Could anyone explain to me why this render occurs and why no effect runs after this rendering? Thank you in advance

CodePudding user response:

It seems that your useEffect is setting the state with the setTrackProgress on the initial render of the component. This is because trackIndex starts at 1 which is lower than 5. (seen by the if(trackIndex<5)) Notice that you haven't provided array dependency to useEffect as the second parameter. According to react-documentation this means the effect will only occur once after the first initial render of the component.

Also, I would suggest adding useCallback to your clickHandler in order to prevent re-defining the function for every render. (According to react-documentation)

CodePudding user response:

You're practically making an infinite loop, but React saves you. The first render log is the initial render, then the useEffect is executed and your component re-renders, leading to the 2nd render log and the first effect; ... log. Now a 2nd useEffect is executed. However, the value of trackIndex hasn't changed, so your if statement will evaluate true and updates trackProgress with the same state/value(1). This leads to another re-render and the third render log. Now, you would think that a 3rd useEffect would be executed, but React is smart enough to know when state hasn't changed and thus doesn't execute the useEffect.

Add dependencies to your useEffect as stated above. That'll solve your problem.

useEffect(
  ...
, [trackIndex])
  • Related