react中的错误捕获
在 React 中捕获组件错误主要有两种核心方式:错误边界(Error Boundary) 和 try/catch 捕获,分别适用于不同场景。
1. 错误边界(Error Boundary):捕获子组件渲染错误
错误边界是 React 提供的一种类组件,专门用于捕获子组件树中的 JavaScript 错误,并提供降级 UI(替代崩溃的组件),而不会导致整个应用崩溃。
核心原理:
通过类组件的两个生命周期方法捕获错误:
static getDerivedStateFromError(error)
:渲染降级 UI(更新 state)。componentDidCatch(error, errorInfo)
:记录错误信息(如日志上报)。
使用示例:
jsx
// 定义错误边界组件
class ErrorBoundary extends React.Component {
state = {hasError: false, error: null};
// 错误发生后更新状态,渲染降级 UI
static getDerivedStateFromError(error) {
return {hasError: true, error};
}
// 记录错误信息(可选)
componentDidCatch(error, errorInfo) {
console.error("组件错误:", error, errorInfo);
// 可在此处上报错误到日志服务
}
render() {
if (this.state.hasError) {
// 自定义降级 UI
return this.props.fallback || <div>发生错误,请刷新页面重试</div>;
}
// 无错误时渲染子组件
return this.props.children;
}
}
// 使用错误边界包裹可能出错的组件
function App() {
return (
<div>
<h1>正常内容</h1>
{/* 用错误边界包裹可能崩溃的组件 */}
<ErrorBoundary fallback={<div>用户列表加载失败</div>}>
<UserList/>
</ErrorBoundary>
</div>
);
}
// 可能出错的子组件
function UserList() {
// 模拟错误:调用不存在的变量
return <div>{undefinedVariable.map()}</div>;
}
适用场景:
- 捕获子组件的渲染错误(如 JSX 语法错误、组件内部逻辑错误)。
- 捕获生命周期方法中的错误。
- 捕获子组件树中任意深度的错误。
局限性:
- 不能捕获自身错误(只能捕获子组件错误)。
- 不能捕获异步错误(如
setTimeout
、fetch
回调中的错误)。 - 不能捕获事件处理函数中的错误(如
onClick
中的错误)。
2. try/catch:捕获同步和异步错误
对于错误边界无法覆盖的场景(如异步操作、事件处理),需使用原生 try/catch
捕获错误。
适用场景:
事件处理函数(如
onClick
、onChange
):jsxfunction Button() { const handleClick = () => { try { // 可能出错的逻辑 JSON.parse('invalid-json'); } catch (error) { console.error("点击事件错误:", error); } }; return <button onClick={handleClick}>点击</button>; }
异步操作(如
setTimeout
、Promise
、async/await
):jsxfunction DataFetcher() { const [data, setData] = useState(null); useEffect(() => { // 异步请求中的错误捕获 const fetchData = async () => { try { const res = await fetch('/invalid-api'); const data = await res.json(); setData(data); } catch (error) { console.error("接口请求错误:", error); } }; fetchData(); }, []); return <div>{data?.content || '加载中...'}</div>; }
自定义 Hooks 中的逻辑错误:
jsxfunction useCustomHook() { try { // 可能出错的逻辑 if (someCondition) { throw new Error("自定义 Hooks 错误"); } } catch (error) { console.error("Hooks 错误:", error); } }
3. 全局错误捕获(补充方案)
对于未被错误边界和 try/catch
捕获的全局错误,可通过以下方式兜底:
- 捕获 React 渲染外的错误:jsx
// 捕获同步代码错误 window.addEventListener('error', (event) => { console.error("全局同步错误:", event.error); }); // 捕获未处理的 Promise 错误(如 fetch 失败未 catch) window.addEventListener('unhandledrejection', (event) => { console.error("未处理的 Promise 错误:", event.reason); event.preventDefault(); // 阻止浏览器默认提示 });
总结:错误捕获方案选择
错误类型 | 推荐方案 |
---|---|
子组件渲染错误 | 错误边界(Error Boundary) |
生命周期方法错误 | 错误边界 |
事件处理函数错误 | try/catch |
异步操作错误(Promise/setTimeout) | try/catch |
全局未捕获错误 | window.error / unhandledrejection |
通过组合使用这些方案,可以全面覆盖 React 应用中的各类错误场景,提升应用的健壮性。