渲染测试与错误诊断
测试怎样等待 React 更新完成再断言?
- act: 使用
await act(async () => { ... })包裹渲染和交互,让相关更新与 Effect 被处理后再检查可观察结果; - 异步选择: 优先使用异步形式,避免依赖同步版本在复杂调度下的偶然表现;
- 工具集成: 常用 React 测试工具已经包装 act,应先使用其公开接口,不机械地重复嵌套;
import { act } from "react";
import { createRoot } from "react-dom/client";
const container = document.createElement("div");
document.body.append(container);
const root = createRoot(container);
await act(async () => {
root.render(<Counter />);
});
await act(async () => {
container.querySelector("button").click();
});
// 在这里断言用户可见结果。
await act(async () => {
root.unmount();
});
container.remove();
act 能否自动完成任意外部异步工作?
- 等待边界: 测试仍需让目标请求、Promise 或模拟计时器到达所需状态,act 不会自动解决永远 pending 的外部任务;
- 环境配置: 测试运行器需要提供合适 DOM 与 act 支持,必要时按运行器约定启用 IS_REACT_ACT_ENVIRONMENT;
- 断言目标: 验证界面和副作用结果,不以内部组件执行次数作为默认契约;
Owner Stack 能补充怎样的错误上下文?
- 创建关系: captureOwnerStack() 在开发环境可获得创建当前元素的组件链,与显示渲染层级的 componentStack 不同;
- 可用时机: 组件渲染、Effect、React 事件或 React 错误处理器等受支持上下文可读取,没有可用上下文时返回 null;
- 生产限制: 开发诊断能力不能作为生产业务逻辑前提,调用应位于开发条件内,生产错误记录使用稳定的错误回调信息;
import * as React from "react";
function reportDevelopmentContext() {
if (process.env.NODE_ENV !== "production") {
console.log(React.captureOwnerStack?.());
}
}