1

this is an experimental code to represent probable misunderstanding of how react works https://jsfiddle.net/Dr_Coder/h6da2jku/78/

const App = () => {
      const {
        useState,
        useEffect
      } = React;
    
    const [firstCount, setFirstCount] = useState(0);
    const [secondCount, setSecondCount] = useState(0)
    
    const increment = () => setFirstCount(firstCount + 1)
    useEffect(() => {
     if(firstCount >= 1) setSecondCount(firstCount)
     
     const timer = setTimeout(() => {
      setFirstCount(0)
     }, 1000);
     
     return () => clearTimeout(timer)
    }, [firstCount, secondCount]);
    
      return (<div className = "app" >
       <button onClick={increment}>click  {firstCount}</button>
       <p>{secondCount}</p>
      < /div>
      )
    }
    
ReactDOM.render( < App / > , document.getElementById('root'))
<div id="root">

</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.12.0/umd/react-dom.production.min.js"></script>

in my mind i think this happens:

1 - clicking the button and this will increment firstCount

2 - rendering with the new value of firstCount

3 - useEffect will work because there is a change in firstCount dependency value

4 - the condition is true and this will change the value of secondCount to be equal to the value of firstCount

5 - this will render component again with the new value of secondCount

6 - timer finishes, and set firstCount to 0, this will render component again

7 - after render useEffect will work, the condition is false, nothing happens

Is this what really happening in the code, the life cycle of a react component is overwhelming, and i hope someone clarify what is exactly happening in the code!

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
Code Eagle
  • 1,293
  • 1
  • 17
  • 34
  • 1
    Yes, your description fits. "What's really happening" is a very very complex broad topic, it would be good if you could limit that to the functionality of one single function or so. – Jonas Wilms Jun 08 '20 at 09:48
  • @JonasWilms - *Mostly*, they missed out a couple of important things I was explaining in my answer when the question was closed. – T.J. Crowder Jun 08 '20 at 09:48
  • but why the question closed?? @T.J.Crowder – Code Eagle Jun 08 '20 at 09:51
  • Seems right, I'm not really sure what you're asking. The example you've written is very clear. Did you expect a different behaviour from this code? – amit Jun 08 '20 at 09:51
  • 1
    @CodeEagle - I didn't vote to close it, and did vote to reopen it. But the close reason given was that it needed more focus. – T.J. Crowder Jun 08 '20 at 09:51
  • @T.J.Crowder Quickly answer before it is closed – mplungjan Jun 08 '20 at 09:52
  • @t.j. well, but which things are important and which aren't? This is too broad, but I certainly won't stop you from answering :) – Jonas Wilms Jun 08 '20 at 09:53
  • @CodeEagle You might want to explain your concerns about your explanation – mplungjan Jun 08 '20 at 09:53
  • @mplungjan I read alot about life cycle in react but it is overwhelming to me, so i created an example and asking if my understanding is right, thanks – Code Eagle Jun 08 '20 at 09:55
  • @JonasWilms - I agree it's really a judgement call about whether it needs more focus. I can see the argument. :-) – T.J. Crowder Jun 08 '20 at 09:56

1 Answers1

2

Yes, that's mostly right, but:

  • You missed out a small bit prior to #1: The first render will call the useEffect callback. The condition is false, but a timer is set; unless you do something within a second, firstCount is set to 0 by the timer callback.

  • The "nothing happens" isn't true in #7 - the useEffect callback still starts a timer, and a second later, the timer still fires. You just don't notice because it's setting the value firstCount already has (0). You can see that if you step through in the debugger or use some console.logs:

const {
    useState,
    useEffect
} = React;

const App = () => {

    console.log("App called");

    const [firstCount, setFirstCount] = useState(0);
    const [secondCount, setSecondCount] = useState(0);

    const increment = () => setFirstCount(firstCount + 1);

    useEffect(() => {
        console.log("useEffect callback");
        if (firstCount >= 1) {
            console.log("useEffect callback - setSecondCount to " + firstCount);
            setSecondCount(firstCount);
        }

        console.log("useEffect callback - start timer");
        const timer = setTimeout(() => {
            console.log("timer fired, setFirstCount(0)");
            setFirstCount(0)
        }, 1000);

        return () => {
            console.log("useEffect cleanup callback, cancel timer [if it hasn't run]");
            clearTimeout(timer);
        };
    }, [firstCount, secondCount]);

    return (
        <div className = "app">
        <button onClick={increment}>click  {firstCount}</button>
        <p>{secondCount}</p>
        </div>
    );
}
    
ReactDOM.render(<App/> , document.getElementById('root'))
<div id="root">

</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.12.0/umd/react-dom.production.min.js"></script>

You can learn more about the React component lifecycle, specifically in regard to hooks, in this article by Dan Abramov. It's ostensibly about useEffect, but really it's about the component lifecycle.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875