React函数组件中的Error Boundary为什么无法捕获子组件错误?
大家好,我在用React 18写一个表单组件时遇到了问题。按照文档把错误边界写成类组件包裹住了子元素,但子组件报错时页面还是会直接崩溃,控制台显示”Uncaught Error: …”
我尝试过两种方式:一是直接用类组件做边界,二是用React.useState()配合error boundaries的函数组件写法。但无论哪种,当子组件触发错误时页面都直接显示白屏。
这是我的代码结构:
class FormErrorBoundary extends React.Component {
state = { error: null }
static getDerivedStateFromError(err) {
return { error: err };
}
render() {
return this.state.error ? 出错了!
: this.props.children;
}
}
function MyForm() {
// 这里子组件会抛出错误
return (
<FormErrorBoundary>
<InputField/> {/* 这里会抛出TypeError */}
</FormErrorBoundary>
)
}
控制台报错信息显示错误确实来自InputField,但边界组件根本没有捕获到,直接显示全局错误了。是不是React 18之后有什么新变化?或者我的边界写法哪里错了?
第一,检查下是不是在InputField组件里抛出了异步错误。Error Boundary只能捕获渲染过程中的同步错误,异步错误需要用try/catch手动处理。比如这种情况:
第二,确保InputField的错误确实发生在render阶段。比如在render里直接这么写肯定能被捕获:
第三,React 18的并发模式可能会影响错误捕获,试试在根组件外包裹StrictMode看看。不过这个概率较小。
建议你先在InputField里直接throw一个同步错误测试下,如果能捕获到说明是异步问题,不能的话可能是浏览器兼容或者React版本问题。
还有个小细节,你的ErrorBoundary组件里最好加个componentDidCatch来记录错误,虽然这不是导致问题的原因:
InputField是在 render 阶段同步抛错,且没有被函数组件拦截。你的类组件写法没问题,但 React 18 中如果用并发模式可能延迟显示错误。加个
componentDidCatch看看实际错误:包一层就行,别在函数组件里直接 throw。