How to avoid React returning an old state (closures)

Let's assume that you have the following component in React:

jsx
import React, { useEffect, useState } from 'react';

const App = () => {
    
    const [clicks, setClicks] = useState(0);
    
    console.log(clicks);
    
    useEffect(() => {
        
        setTimeout(() => {
        
            setClicks(clicks + 1);
            
        }, 3000);
        
    }, [])
    
    const increaseClicks = () => {
    
        setClicks(clicks + 1);
        
    }
    
    return(
        <button onClick = {increaseClicks}>Click me</button>
    );
    
}

export default App;

If you click on the button before the first 3 seconds, the console will print 1 twice instead of increasing the value. This is because JavaScript closures, the value of clicks inside setTimeout() doesn't get updated after clicking on the button.

To force React to update a value, use an arrow function:

javascript
setTimeout(() => {

    setClicks(clicks => clicks + 1);

}, 3000);

Now if you click before the first 3 seconds, the value of clicks will get updated anyway.

Hi, I'm Erik, an engineer from Barcelona. If you like the post or have any comments, say hi.