React ErrorBoundary 无法捕获“无法读取未定义的属性”
我在使用 React ErrorBoundary 时遇到了一个奇怪的边缘情况。如果异常发生在内联表达式中,则不会被处理。例如:
const page = webtexts[courseId].pages[pageFamilyId]; // Returns undefined
...
<ErrorBoundary>
// "Cannot read properties of undefined (reading 'page_name')" won't be processed in ErrorBoundary
<span>{page.page_name}</span>
</ErrorBoundary>
但是如果我将组件中有问题的地方包裹起来,它就可以正常工作。
const page = webtexts[courseId].pages[pageFamilyId]; // Returns undefined
...
const WrapFailingPage: React.FC<{ page: any }> = ({ page }) => {
return <span>{page.page_name}</span>;
};
...
<ErrorBoundary>
<WrapFailingPage page={page} /> // The error is properly processed in ErrorBoundary
</ErrorBoundary>
对于演示,我制作了一个简单的 Codepen - https://codepen.io/OlexanderD/pen/wvpdpxY< /a>.
ErrorBoundary
应该这样做吗?为什么内联表达式可能会出现问题?
I faced a weird edge case with React ErrorBoundary. Exceptions are not being processed if they happen in inline expression. For example:
const page = webtexts[courseId].pages[pageFamilyId]; // Returns undefined
...
<ErrorBoundary>
// "Cannot read properties of undefined (reading 'page_name')" won't be processed in ErrorBoundary
<span>{page.page_name}</span>
</ErrorBoundary>
But if I wrap a problematic place in the component, it works properly.
const page = webtexts[courseId].pages[pageFamilyId]; // Returns undefined
...
const WrapFailingPage: React.FC<{ page: any }> = ({ page }) => {
return <span>{page.page_name}</span>;
};
...
<ErrorBoundary>
<WrapFailingPage page={page} /> // The error is properly processed in ErrorBoundary
</ErrorBoundary>
For the demo, I made a simple Codepen - https://codepen.io/OlexanderD/pen/wvpdpxY.
Should the ErrorBoundary
behave in that way? Why the inline expressions can be problematic?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
TL;DR
ErrorBoundary
仅跟踪使用React.createElement(React.Component / React.[V]FC)
创建的代码部分。因此,如果您从自定义 React 组件返回损坏的 JSX,ErrorBoundary 将会拾取它并进行处理。详细信息:
为随附的 Codepen https://codepen.io/OlexanderD/pen/wvpdpxY
一些术语:
element
- 任何 HTML 标签。它将被处理为React.createElement('div', ...)
component
- 任何 React 组件,而不是原生 HTML 标签。我将被处理为React.createElement(MyComponent, ...)
根据 文档,
ErrorBoundary
只能处理其子组件树中的异常,但我尝试从元素捕获异常。React.createElement() 可以接收 2 种类型的参数:标签name (
div
,span
, ...) 或 React 组件。因此,当我们简单地使用并将其传递给父
div
时,React 将生成 此代码:如您所见,我们传递一个元素作为部分的
props.children
用于父div
。因此,ErrorBoundary
不会将其作为组件树的一部分进行处理。但是如果我们使用像
FailingComponent
这样的包装器,生成的 JSX 将看起来像这样:现在我们将组件传递给父
div
的props.children
。ErrorBoundary
会将FailingComponent
的结果处理为组件树的一部分。TL;DR
ErrorBoundary
tracks only the code parts that were created withReact.createElement(React.Component / React.[V]FC)
. Therefore, if you return a broken JSX from a custom React component,ErrorBoundary
will pick it up and process.Details:
Examples are made for the attached Codepen https://codepen.io/OlexanderD/pen/wvpdpxY
A bit of terminology:
element
- any HTML tag. It'll be processed asReact.createElement('div', ...)
component
- any React component, not native HTML tag. I'll be processed asReact.createElement(MyComponent, ...)
According to the docs,
ErrorBoundary
can process exceptions only in their child component tree, but I tried to catch an exception from the element.React.createElement() can receives 2 types of arguments: tag name (
div
,span
, ...) or React component. Therefore, when we simply use<div>{fail.absurdIntentionalError}</div>
and pass it to parentdiv
the React will generate this code:As you can see we're passing an element as the part of the
props.children
for the parentdiv
. Therefore theErrorBoundary
won't process it as the part of the component tree.But if we use some wrapper like
FailingComponent
, the generated JSX will look like this:Now we're passing the component to the
props.children
for the parentdiv
. And theErrorBoundary
will process the result of theFailingComponent
as the part of the component tree.当您未正确启动Bugsnag时,有时会发生这种情况。
这是触发错误的示例:
以上将触发“ React ErrorBoundary catchary”无法读取未定义的“错误”属性。
因此,在这种情况下,包括该代码将解决以下问题:
It happens sometimes when you have not initiated Bugsnag correctly.
Here is an example that triggers an error:
The above will trigger the "React ErrorBoundary doesn't catch "cannot read properties of undefined" error.
Therefore, in this case including that code will fix the issue as below: