React ErrorBoundary 没有捕捉到 "cannot read properties of undefined"
React ErrorBoundary doesn't catch "cannot read properties of undefined"
我在使用 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。
ErrorBoundary
应该那样做吗?为什么内联表达式会出现问题?
TL;DR
ErrorBoundary
仅跟踪使用 React.createElement(React.Component / React.[V]FC)
创建的代码部分。因此,如果您 return 来自自定义 React 组件的损坏的 JSX,ErrorBoundary
将拾取它并进行处理。
详情:
示例是为随附的代码笔制作的https://codepen.io/OlexanderD/pen/wvpdpxY
一些术语:
element
- 任何 HTML 标签。它将被处理为 React.createElement('div', ...)
component
- 任何 React 组件,而不是原生 HTML 标签。我将被处理为 React.createElement(MyComponent, ...)
根据 the docs,ErrorBoundary
只能在其子 component 树 中处理异常 ,但我试图从 元素 .
捕获异常
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 parent div
the React will generate this code:
React.createElement(
"div",
null,
React.createElement("button", ...),
showFailingChild &&
React.createElement("div", null, fail.absurdIntentionalError)
);
如您所见,我们传递了一个 元素 作为父 props.children
的一部分20=]。因此 ErrorBoundary
不会处理 它作为 component tree 的一部分。
但是如果我们使用像 FailingComponent
这样的包装器,生成的 JSX 将看起来 like this:
React.createElement(
"div",
null,
React.createElement("button", ...),
showFailingComponent &&
React.createElement(FailingComponent, null)
);
现在我们将 组件 传递给父 div
的 props.children
。 ErrorBoundary
将处理 FailingComponent
的结果作为 component tree.[=36= 的一部分]
我在使用 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。
ErrorBoundary
应该那样做吗?为什么内联表达式会出现问题?
TL;DR
ErrorBoundary
仅跟踪使用 React.createElement(React.Component / React.[V]FC)
创建的代码部分。因此,如果您 return 来自自定义 React 组件的损坏的 JSX,ErrorBoundary
将拾取它并进行处理。
详情:
示例是为随附的代码笔制作的https://codepen.io/OlexanderD/pen/wvpdpxY
一些术语:
element
- 任何 HTML 标签。它将被处理为React.createElement('div', ...)
component
- 任何 React 组件,而不是原生 HTML 标签。我将被处理为React.createElement(MyComponent, ...)
根据 the docs,ErrorBoundary
只能在其子 component 树 中处理异常 ,但我试图从 元素 .
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 parent div
the React will generate this code:
React.createElement(
"div",
null,
React.createElement("button", ...),
showFailingChild &&
React.createElement("div", null, fail.absurdIntentionalError)
);
如您所见,我们传递了一个 元素 作为父 props.children
的一部分20=]。因此 ErrorBoundary
不会处理 它作为 component tree 的一部分。
但是如果我们使用像 FailingComponent
这样的包装器,生成的 JSX 将看起来 like this:
React.createElement(
"div",
null,
React.createElement("button", ...),
showFailingComponent &&
React.createElement(FailingComponent, null)
);
现在我们将 组件 传递给父 div
的 props.children
。 ErrorBoundary
将处理 FailingComponent
的结果作为 component tree.[=36= 的一部分]