无测试文件的Next.js项目出现React act()状态更新警告是什么原因?
无测试文件情况下React act报错的原因与解决方案
你碰到的这段报错的中文含义如下:
测试过程中,会触发React状态更新的代码需要被包裹在
act(...)中:act(() => { /* 触发更新状态的事件 */ }); /* 对输出做断言 */该逻辑可以保证你测试到的行为和用户在浏览器中看到的完全一致。
这个报错本质是React开发环境的内置校验提示,并非只有写测试用例时才会触发,只要开发模式下出现了未被React同步渲染流程追踪到的状态更新,就有可能弹出该提示。
非测试场景下的常见触发原因
- 组件卸载后仍执行状态更新:例如在
useEffect中发起异步请求,请求返回前用户就跳转页面关闭了当前组件,请求回调执行setState时,组件生命周期已经脱离了React的同步渲染流程,就会误触发act相关校验提示 - 第三方依赖引入测试逻辑:你项目中安装的某个依赖包自带测试相关代码,或者你在业务代码中误引入了
@testing-library/react这类测试包的方法并调用,也会触发测试场景下的act校验 - 旧版本React的已知bug:React 16、17的部分小版本对异步状态更新的追踪逻辑存在缺陷,只要是
setTimeout、Promise回调中触发的状态更新,都有可能误弹出该act提示,和实际测试行为完全无关
对应解决方法
- 清理组件异步副作用:在
useEffect的清理函数中添加取消请求的逻辑,或者设置mounted标记,组件卸载后不再执行状态更新,参考代码如下:
useEffect(() => { let isMounted = true fetch('/api/data').then(res => res.json()).then(data => { if (isMounted) { setData(data) } }) return () => { isMounted = false } }, [])
- 全局检索项目代码,排查是否有误引入测试依赖的调用,例如
render、fireEvent这类来自测试库的方法 - 若是React旧版本bug导致,可升级到React 18+版本;也可以给触发异步更新的逻辑手动添加act包裹(生产环境下act是空函数,不会影响性能),参考代码如下:
import { act } from 'react-dom/test-utils' // 你的异步更新逻辑 act(() => { setState(更新后的值) })
内容的提问来源于stack exchange,提问作者Lagu Longa
相关产品推荐
相关产品推荐

