React Testing Library中使用异步user event出现ACT警告如何解决?
解决React测试中的ACT警告问题
问题原因
你遇到的ACT警告,核心原因是测试中使用了旧的DOM元素引用,没有等待组件更新后获取最新的DOM节点。虽然你的组件没有异步逻辑,但React状态更新会触发重新渲染,你提前保存的boardChildren数组里的元素是渲染初期的旧节点,点击后组件重新渲染,旧节点被替换,此时断言旧节点会导致React无法确认所有更新已完成,从而抛出ACT警告。
解决方案
修改测试代码,避免提前保存DOM元素引用,每次操作或断言前都重新从DOM中查询最新的元素;或者使用waitFor确保断言在组件更新完成后执行。
方案1:每次操作/断言前重新查询DOM
test("when user clicks second time, the clicked element gets 'circle' class", async () => { render(<Board />); // 第一次点击:获取最新的子元素 await user.click(screen.getAllByTestId("board-child")[0]); // 第二次点击:重新获取最新的子元素 await user.click(screen.getAllByTestId("board-child")[1]); // 断言:再次获取最新的目标元素 expect(screen.getAllByTestId("board-child")[1]).toHaveClass("circle"); });
方案2:使用waitFor等待更新完成
import { waitFor } from '@testing-library/react'; test("when user clicks second time, the clicked element gets 'circle' class", async () => { render(<Board />); await user.click(screen.getAllByTestId("board-child")[0]); await user.click(screen.getAllByTestId("board-child")[1]); // 等待组件更新完成后再执行断言 await waitFor(() => { expect(screen.getAllByTestId("board-child")[1]).toHaveClass("circle"); }); });
额外优化建议
你的组件中handleUserClick里使用了多个@ts-ignore,可以通过类型断言消除类型错误,比如:
const handleUserClick = (e: React.MouseEvent<HTMLDivElement>) => { const target = e.target as HTMLDivElement; const index = Number(target.dataset.number); if (isNaN(index) || board[index] !== null) return; setBoard(p => p.map((el, i) => i === index ? currentSign : el)); setCurrentSign(p => p === "cross" ? "circle" : "cross"); };
内容的提问来源于stack exchange,提问作者Jakub Godlewski
相关产品推荐
相关产品推荐

