React 18中waitForNextUpdate函数的替代方案咨询
React 18 下替代
waitForNextUpdate 的测试方案 问题说明
项目升级到 React 18 后,原来用来测试会话管理 Hook 的 @testing-library/react-hooks 库被废弃了。之前常用的 waitForNextUpdate 函数没被迁移到官方测试库,强制安装旧版本又会和 React 18 产生冲突,导致大量测试直接失败。
可行替代方案
1. 用 React Testing Library 的 waitFor + 状态断言(官方推荐)
React 18 官方推荐的 @testing-library/react 提供了 waitFor 函数,可以通过断言 Hook 的状态变化,替代原来 waitForNextUpdate 单纯等待更新的逻辑。
示例改造(以常见测试场景为例)
旧版测试代码:
import { renderHook, waitForNextUpdate } from '@testing-library/react-hooks'; import useSession from './useSession'; test('会话过期后自动刷新', async () => { const { result } = renderHook(() => useSession()); // 触发过期逻辑 act(() => { result.current.triggerExpiry(); }); // 等待 Hook 更新 await waitForNextUpdate(); // 断言更新后的状态 expect(result.current.isRefreshed).toBe(true); });
React 18 兼容版:
import { renderHook, act, waitFor } from '@testing-library/react'; import useSession from './useSession'; test('会话过期后自动刷新', async () => { const { result } = renderHook(() => useSession()); // 触发过期逻辑 act(() => { result.current.triggerExpiry(); }); // 用 waitFor 等待状态变为预期值 await waitFor(() => { expect(result.current.isRefreshed).toBe(true); }); });
2. 手动等待异步任务 + 状态检查
如果 Hook 的更新依赖 API 请求这类异步操作,可以直接等待微任务队列清空后,再断言状态:
import { renderHook, act } from '@testing-library/react'; import useSession from './useSession'; test('刷新会话后更新用户信息', async () => { const { result } = renderHook(() => useSession()); act(() => { result.current.refreshSession(); }); // 等待所有异步操作完成 await Promise.resolve(); // 断言状态变化 expect(result.current.userInfo).not.toBeNull(); });
3. 自行封装简化版 waitForNextUpdate
如果大量测试都需要类似等待更新的逻辑,可以自己封装一个工具函数,利用 Hook 的状态变化触发等待:
// 自定义工具函数 async function waitForNextUpdate(result) { return new Promise(resolve => { // 监听 result.current 的变化 const observer = new MutationObserver(() => { observer.disconnect(); resolve(); }); observer.observe(result, { attributes: true }); }); } // 使用示例 test('切换会话后更新状态', async () => { const { result } = renderHook(() => useSession()); act(() => { result.current.switchSession('new-session-id'); }); await waitForNextUpdate(result); expect(result.current.activeSessionId).toBe('new-session-id'); });
注意事项
- 所有触发状态更新的操作,必须包裹在
act()中,否则 React 18 会抛出警告。 - 优先使用
waitFor+ 具体断言的方式,这是官方推荐的测试逻辑,相比单纯等待更新,测试意图更清晰。 - 如果 Hook 依赖定时器,记得配合
jest.useFakeTimers()和jest.runAllTimers()进行测试。
内容的提问来源于stack exchange,提问作者Jordan Campbell
相关产品推荐
相关产品推荐

