React useState异步代码没有更新?

作者站长头像
站长
· 阅读数 15

背景:

React代码如下

import { useState } from 'react';

export default function App() {
  const [count, setCount] = useState(0);
  const handleClick = () => {
    setCount(count + 1);
    setTimeout(() => {
      console.log(count, 'end'); // 还是 0!
    }, 5000);
  }
  return (
    <>
      <button onClick={handleClick}>+1</button>
      <span>{count}</span>
    </>
  );
}

setCount的更新是异步更新的,setTimeout也是异步的,为什么点击,console.log打印的是0,而不是1。

尝试:

尝试用普通js函数进行比较,js代码如下

function outerFunction() {    
  let count = 0;  
    
  function innerFunction() {    
    console.log(count);  
  }    
    
  count = 1;  // 将count更新为1  
  setTimeout(innerFunction, 5000); 
    
  count = 2; 
}    
  
outerFunction();

console.log打印的是最新的值2。

疑问: 两段代码的打印结果不同,是什么原因呢?

回复
1个回答
avatar
test
2024-06-20
setTimeout(() => {
  console.log(count, 'end'); // 还是 0!
}, 5000);

你可以把react组件的每次渲染理解为生成了一个平行宇宙。

初始化渲染时生成的平宇宙,其count值为0,所以就算定时器延迟一年执行,它也只能输出0

当你调用setCount(count + 1),这触发了第二次渲染,又生成了一个平行宇宙,这个平行宇宙中的count1,这个宇宙中的定时器也就只能输出1

去掉定时器帮助理解

const handleClick = () => {
  setCount(count + 1);

  console.log(count, 'end');
}
// 两者其实是一样的,加上定时器并不会让count拥有穿透平行宇宙的能力
const handleClick = () => {
  setCount(count + 1);
  setTimeout(() => {
    console.log(count, 'end');
  }, 5000);
}
回复
likes
适合作为回答的
  • 经过验证的有效解决办法
  • 自己的经验指引,对解决问题有帮助
  • 遵循 Markdown 语法排版,代码语义正确
不该作为回答的
  • 询问内容细节或回复楼层
  • 与题目无关的内容
  • “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容