React 错误边界:ErrorBoundary 组件
React 应用在运行时可能因代码异常导致整个页面崩溃。错误边界(Error Boundary)是一种特殊组件,用于捕获其子组件树中 JavaScript 错误,并显示备用 UI,而不是让整个应用白屏或崩溃。创建一个 ErrorBoundary 组件能显著提升用户体验和应用稳定性。
创建基础 ErrorBoundary 组件
-
新建一个名为
ErrorBoundary.js的文件。 -
导入必要的 React 模块:
import React from 'react'; -
定义一个类组件并继承
React.Component:class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false }; } } -
实现
static getDerivedStateFromError方法:该方法在子组件抛出错误后被调用,用于更新状态以触发备用 UI 渲染。static getDerivedStateFromError(error) { return { hasError: true }; } -
可选:实现
componentDidCatch方法:用于记录错误信息(例如上报到监控系统)。componentDidCatch(error, errorInfo) { console.error("Error caught by boundary:", error, errorInfo); } -
在
render方法中根据状态决定渲染内容:render() { if (this.state.hasError) { return <h2>出了点问题,请稍后再试。</h2>; } return this.props.children; } -
导出组件:
export default ErrorBoundary;
完整代码如下:
import React from 'react';
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
console.error("Error caught by boundary:", error, errorInfo);
}
render() {
if (this.state.hasError) {
return <h2>出了点问题,请稍后再试。</h2>;
}
return this.props.children;
}
}
export default ErrorBoundary;
在应用中使用 ErrorBoundary
-
在需要保护的组件外层包裹
<ErrorBoundary>。例如,在App.js中:import React from 'react'; import ErrorBoundary from './ErrorBoundary'; import UserProfile from './UserProfile'; function App() { return ( <div> <h1>我的应用</h1> <ErrorBoundary> <UserProfile /> </ErrorBoundary> </div> ); } export default App; -
确保错误发生在
ErrorBoundary的子组件内部。注意:错误边界无法捕获以下情况的错误:- 事件处理函数中的错误
- 异步代码(如
setTimeout或Promise回调) - 服务端渲染过程中的错误
- 错误边界自身抛出的错误
自定义错误显示与重置机制
为提升交互体验,可添加“重试”按钮让用户手动恢复界面。
-
在
ErrorBoundary的状态中增加error和errorInfo字段(可选,用于调试):constructor(props) { super(props); this.state = { hasError: false, error: null, errorInfo: null }; } -
修改
componentDidCatch以保存错误详情:componentDidCatch(error, errorInfo) { this.setState({ hasError: true, error: error, errorInfo: errorInfo }); } -
添加一个重置方法:
handleReset = () => { this.setState({ hasError: false, error: null, errorInfo: null }); }; -
在错误 UI 中加入重试按钮:
render() { if (this.state.hasError) { return ( <div> <h2>出了点问题,请稍后再试。</h2> <button onClick={this.handleReset}>重试</button> </div> ); } return this.props.children; }
更新后的完整组件:
import React from 'react';
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false, error: null, errorInfo: null };
}
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
this.setState({
hasError: true,
error: error,
errorInfo: errorInfo
});
}
handleReset = () => {
this.setState({ hasError: false, error: null, errorInfo: null });
};
render() {
if (this.state.hasError) {
return (
<div>
<h2>出了点问题,请稍后再试。</h2>
<button onClick={this.handleReset}>重试</button>
</div>
);
}
return this.props.children;
}
}
export default ErrorBoundary;
注意事项与最佳实践
| 场景 | 是否能被捕获 | 说明 |
|---|---|---|
| 子组件 render 中的错误 | ✅ | 错误边界的主要用途 |
| 事件处理函数(如 onClick)中的错误 | ❌ | 应使用 try/catch 处理 |
| 异步回调(如 fetch.then)中的错误 | ❌ | 需在异步逻辑内部捕获 |
| useEffect 中的错误 | ❌ | React 16+ 中不会触发错误边界 |
| 服务端渲染错误 | ❌ | 需在服务器中间件中处理 |
不要将错误边界包裹整个应用根节点。建议按功能模块划分,例如分别保护导航栏、主内容区、侧边栏等,避免局部错误影响全局。
避免在错误边界中执行复杂逻辑。getDerivedStateFromError 和 componentDidCatch 应保持轻量,防止二次崩溃。
测试错误边界行为:可临时在子组件中加入 throw new Error('Test') 验证备用 UI 是否正常显示。

暂无评论,快来抢沙发吧!