useStateCounterintuitive asynchronous update problem

function UseStateDemo() {
    const [num,setNum] = useState(0)
    const addNumber = () = >{
        setTimeout(() = >{
            setNum(() = > num + 1)},2000)}return {num}
}
Copy the code

Conclusion: Num accessed in setTimeout is a variable in the closure, which is saved after the initial function execution. After the next state update, the next render generates a new function scope, so setTimeout will still use the old value to update after the delay.

In fact, this is a simple closure problem, and I’ll try to prove it in the following code.

function preserveNum(){
  let num = 0
  setTimeout(() = >{
    num++
  },1000)
  return function(){
    console.log(num)
  }
}

const printNum = preserveNum()

setTimeout(() = >{
  printNum() / / 1
  const newPrintNum = preserveNum() // Execute again
  newPrintNum() / / 0
},2000)
Copy the code

It is well understood from this demo that a new internal scope has been created under the newly executed preserveNum, which of course is unrelated to the function returned by the first execution.

You might want to try the following weird code again

function printAge() { const [state,setState] = useState(0) const Kent = { age: 0} const add = ()=>{setTimeout(()=>{setState(kt. age ++)})} return {state + 'Kent age is' + Kt. age}}Copy the code

This is also a common problem with things like useMemo and useCallback, where they cache values or functions, which are not fancy stuff, but rely on closures to do it.

React Hook abstractions are actually quite intuitive in business, it just depends on how they are used correctly.

If there are any mistakes in this article, please correct and communicate with us