Search code examples
javascriptreactjsuse-effect

is this what is happening in this react code?


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!


Solution

  • 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.