DevTracePad↗
简体中文 ⌄
English简体中文日本語

实践手册 / 报错分析

堆栈是线索,不是结论

如何把异常转化为可以验证的解释,而不是直接采用第一个看起来合理的修复。

从实际发生的事情开始

先保留异常类型、消息以及第一个属于你自己代码的调用帧,再加入相关函数和传入的值。堆栈描述失败时的调用路径,但通常不能证明某个更早的值为什么变得无效。ProductList 示例中,错误消息指出接收者为 undefined,旁边的 useState() 才补充了“首次渲染时初始值不正确”的证据。

保留竞争性解释

初始值错误、响应结构变化或错误分支赋了不同类型,都可能造成相似症状,却需要不同检查。为每个假设寻找能区分它们的观察。“把所有内容都打出来”不如在失败表达式前检查 Array.isArray,并核对响应外层结构。应在不会把敏感数据写入日志的环境里进行。

区分保护措施与根因修复

把 products.map 改成 products?.map 可能避免崩溃,却仍然没有处理非法响应。初始化数组可以解决首次渲染,但未必能处理后续异常载荷。应写明修改究竟针对哪个条件,并分别设计加载、空数据和失败状态,避免把没有显示内容误认为成功。

用小型测试矩阵闭环

检查首次渲染、非空正常响应、空响应和请求失败。无法测试的情况标记为未验证。把原始失败输入与修改后的代码放在一起。AI 解释提供调查计划,实际观察到的结果才是闭环证据。

拆解一个具体例子

报错分析

编写示例:这份固定结果仅对应示例原文,不是实时 AI 回复。

原始内容

TypeError: Cannot read properties of undefined (reading "map")
 at ProductList (ProductList.jsx:18)
const [products, setProducts] = useState();
return products.map(product => <li key={product.id}>{product.name}</li>);

解析结果

观察
首次渲染对 products 调用 .map,而 useState() 的初始值为 undefined。

可能原因
初始状态不是数组。这段代码支持此解释,但无法说明后续 API 是否返回合法数组。

下一步验证
检查 setProducts 之前的响应结构:数组是响应本身,还是 response.items?

可尝试的修改
使用 useState([]) 初始化,分别处理加载中、空数据和请求失败状态,并在设置状态前验证响应。

回归检查
检查首次渲染、空响应、正常响应和请求失败。本例没有实际运行组件。