实践手册 / 报错分析
堆栈是线索,不是结论
如何把异常转化为可以验证的解释,而不是直接采用第一个看起来合理的修复。
从实际发生的事情开始
先保留异常类型、消息以及第一个属于你自己代码的调用帧,再加入相关函数和传入的值。堆栈描述失败时的调用路径,但通常不能证明某个更早的值为什么变得无效。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([]) 初始化,分别处理加载中、空数据和请求失败状态,并在设置状态前验证响应。 回归检查 检查首次渲染、空响应、正常响应和请求失败。本例没有实际运行组件。