Home > Mobile >  understanding useCallback and setState
understanding useCallback and setState

Time:08-15

I have some simple lines of code to test the useCallback and setState hook. First I try to write like this:

const App = () => {

    const [count, setCount] = useState(0)

    const increase = useCallback(() => {
        setCount(count   1) // Passing value to change state
    }, [])
    console.log(count)

    return (
        <div id="main">
            <h1>Count: {count}</h1>
            <button onClick={increase}>Increase</button>
        </div>
    )
}


export default App;

and then, passing the callback to setCount instead like this:

const App = () => {

    const [count, setCount] = useState(0)

    const increase = useCallback(() => {
        setCount(count => count   1) // Passing callback
    }, [])
    console.log(count)

    return (
        <div id="main">
            <h1>Count: {count}</h1>
            <button onClick={increase}>Increase</button>
        </div>
    )
}


export default App;

I know it is weird to use useCallback in this situation, just for some testing. The question is that why I pass the callback to setCount, the Increase button work correctly, whereas the first one will just re-render on the first click

CodePudding user response:

In the first case useCallback closes over the count and at that time count was 0 so It always changes value to 1

So to make it working you should add count dependency to useCallback as:

CODESANDBOX LINK

const increase = useCallback(() => {
    setCount(count   1); // Passing value to change state
}, [count]);

In the second case it is not taking the value from the closure instead it is taking the current value and adds one to it and set the value.


ADDITIONAL INFO

You can use react-hooks/exhaustive-deps eslint rule to know which dependency is missing and tell you how to correct it.

CodePudding user response:

useCallback() hasn't been used correctly here: the dependencies array should have count in it. So:

const increase = useCallback(() => {
  setCount(count   1) // Passing value to change state
}, [count])

With an empty array as a dependency, it will be memoized for the lifetime of the component and will not update the current count value.

Source: https://reactjs.org/docs/hooks-reference.html#usecallback

Code sandbox

On a side note, using useCallback() is "overoptimizing" in this case, we are complicating the code while the performance impact to the end users is not noticeable. I would only use it to prevent rerenders in complex views e.g. in a huge list.

  • Related