错误边界与恢复
错误边界与恢复 · 阅读后完成下方实验与检查题,再用「标记完成」记录进度。
学习目标
读完你能实现一个可复用的错误边界组件,把可失败的局部组件隔离起来并提供恢复动作;能区分三类失败——渲染错误、事件处理错误、异步请求失败——各自的正确处理位置,不再指望一张网兜住所有问题。
问题场景
课程详情页右侧有个「评分分布」小组件。某天后端返回一条脏数据,它的渲染抛出 TypeError,结果是整页白屏——一个边缘小组件拖死了整个页面。原因:渲染阶段抛出的错误会沿着组件树一路上传,默认直到把整个根卸载,除非路上有组件声明「我来接住」。
核心解释
接住渲染错误的就是错误边界:定义了 getDerivedStateFromError(把错误转成界面)或 componentDidCatch(记录日志等副作用)的 class 组件。函数组件写不了边界,但可以用 class 包一层,内部照常使用函数组件:
class ErrorBoundary extends React.Component {
state = { error: null };
static getDerivedStateFromError(error) {
return { error }; // 渲染降级界面
}
componentDidCatch(error, info) {
console.error("边界捕获:", error.message); // 上报日志放这里
}
render() {
if (this.state.error) return this.props.fallback(this.state.error);
return this.props.children;
}
}
恢复的关键是「修复数据 + 换 key 重建」:只把 error 清空,子组件内部坏掉的状态还在,可能再崩;给被包裹的子树换 key,React 会销毁重建,从源头避开坏状态。
三类失败要分清,边界不是万能网:
function handleSave() {
try { saveSnapshot(); } catch (e) { setTip("保存失败:" + e.message); } // 事件错误:就地 catch
}
async function load() {
try { setData(await api()); }
catch (e) { setLoadError("加载失败,点击重试"); } // 异步失败:转成状态渲染
}
- 渲染错误(渲染函数里抛错):边界负责;事件处理与异步回调里的错误,边界管不到;
- 事件处理错误:不会引发白屏,在处理函数里 try/catch 即可,不交给边界;
- 异步请求失败:Promise 的 reject 发生在边界的捕获范围之外,应在请求层 catch 后转成状态(如 error 字段)再渲染出来。
示例拆解
实验区页面里有一个「评分分布」组件,开关能注入脏数据让它在渲染期抛错:
- 页面级边界模式:勾选脏数据,整页降级为错误提示——这就是粒度太粗的后果,恢复按钮做「修复数据 + 换 key 重建」;
- 组件级边界模式:同样的错误,只有小组件位置显示「暂时不可用」,页面其余部分完全正常;
- 「触发事件错误」按钮:try/catch 就地捕获,只在角落显示一条红色提示,页面无感;
- 异步面板:模拟请求失败,错误态由面板自己的状态渲染,全程不经过错误边界;
- 验证:三种失败逐一触发,确认影响范围与处理位置符合预期。
动手任务
打开本课实验区:
- 两种边界粒度各注入一次脏数据,记录降级范围的差别;执行一次「重试」,观察它先清脏数据再换 key。
- 给边界 fallback 加一个「上报日志」按钮,点击后把错误堆栈输出到 console。
- 把异步面板改成「最多自动重试 2 次,仍失败才显示失败态」,用状态计数实现。
常见错误
- 以为边界能接住事件和异步错误:它们不发生在渲染阶段,边界根本不触发;对应位置用 try/catch 或请求层错误状态。
- 整个页面包一个边界:任何一处崩溃整页降级;边界应贴着「可失败单元」放置。
- 恢复只清 error 不重建:子组件内部坏状态还在,再渲染可能再崩;用 key 重建子树。
- 在 render 里写 try/catch 期望兜住子组件错误:渲染期错误走边界机制,不走 try/catch。
检查与复盘
自查清单:
- 能默写错误边界的两个关键 API 与各自职责(降级界面 / 记录日志)
- 三类失败能各说出正确的处理位置
- 边界粒度贴着可失败组件,恢复用「修复数据 + 换 key」并验证过
参考资料
- React 官方文档:用错误边界捕获渲染错误 —— 官方对边界能力范围的定义
- React 官方文档:componentDidCatch —— 记录错误回调的约定
读完这一课了?
标记完成后,工作台会安排接下来的学习。