0

In the code ( https://jsfiddle.net/xga6w7Lp/ ) , state changes via event handler [ handleClick() ]. And when state changes useEffect will run and inside useEffect I am setting the same state [.setNumOfClicks(numOfClicks); ]. But setting the same state inside the useEffect causing the function ( Counter function ) to re-execute. This should not happen right?

I know this is a weird scenario but I am just playing around to understand how things works under the hood.

In the event handler function , if I set the same state [.setNumOfClicks(numOfClicks); ] then the Counter function is NOT running again and thats as expected because I am not changing the state inside event handler. But , in case of useEffect , the Counter function is running again even though state is not changed.

UPDATE

This question has no relation with Why does React render component for the second time after setting the state to the same value? since it is addressing the issue in general. But in this question - re running the functional component is NOT happening in case of event handler when we set the same state but only in case of useEffect. And hence this is specific to "useEffect" hook.

Code

import React from "react";
import ReactDOM from "react-dom/client";

function App(){
    return(
        <>
            <h1>Counters</h1>
            <section>
                <Counter />
            </section>
        </>
    );
}

function Counter(props){
    console.log("Inside Counter Function....");

    const [numOfClicks,setNumOfClicks] = React.useState(0);
    console.log("numOfClicks = "+numOfClicks);

    React.useEffect(()=>{
        console.log("In useEffect");
        console.log("useEffects => numOfClicks = "+numOfClicks);
        setNumOfClicks(numOfClicks);
    },[numOfClicks]);

    function handleClick(){
        setNumOfClicks(numOfClicks+1);
        console.log("Inside handle Click....");
    }

    return(
        <article>
            <h2>Counter {props.name}</h2>
            <p>You clicked {numOfClicks} times</p>
            <button className="button" onClick={handleClick}>
                Click Me
            </button>
        </article>
    );

}

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App/>);
to-find
  • 33
  • 3
  • It's just an edge case, sometimes React needs another render to bailout the component tree update, nice to notice that it not continues to the rest of the component tree (try to make Counter to render a component and check if the code executes). See the duplicate for more context. – Dennis Vash Aug 17 '23 at 07:13
  • @DennisVash You meant to say create another component and run it inside Counter? If so and if the code executes then what does it mean? – to-find Aug 17 '23 at 07:22
  • It's because you have passed the state numOfClicks as a dependency in the useEffect, so every time you set the state of numOfClicks inside useEffect hook it will re render your react component and cause the infinite re rendering, thats why you should never pass the state as a useEffect dependency if you are updating it inside the useEffect hook. See here for more detailed explaination https://codedamn.com/news/reactjs/useeffect-dependency – Aamir Khan Aug 17 '23 at 09:54
  • @Amir Khan , no infinite re-rendering happening here. when we set the same state inside the useEffet then the functional component is re-executing even though state is not changed. And why it is so? – to-find Aug 17 '23 at 10:21

0 Answers0