为什么 React 仍然渲染带有 Error Boundary 的子组件
Why React still render the child component with Error Boundary
我使用 React 16
和 Error Boundary
功能:
Profile.js
class Profile extends Component {
constructor(props) {
super(props);
this.state = {
// user: {
// name: "Ha (Huck) H.K. NGUYEN"
// }
user: null
};
this.updateUser = this.updateUser.bind(this);
}
updateUser() {
this.setState({ user: null })
}
render() {
const { user } = this.state;
console.log(user);
return <div className="App">
{user.name}
<button onClick={this.updateUser}>
Update
</button>
</div>
}
}
ErrorBoundary.js
class ErrorBoundary extends Component {
constructor(props) {
super(props);
this.state = {
hasError: false
}
}
componentDidCatch(error, errorInfo) {
this.setState({ hasError: true });
}
render() {
const { children } = this.props;
const { hasError } = this.state;
if (hasError) {
return <HasError />
}
return children
}
}
App.js
class App extends Component {
render() {
return <div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h1 className="App-title">Welcome to React</h1>
</header>
<ErrorBoundary>
<Profile />
</ErrorBoundary>
</div>
}
}
我看到功能组件在错误发生后仍然被调用并被捕获。任何人都可以解释为什么调用 render
函数。
不知道的请按照的回答,按esc
键可以看到错误边界。
https://codesandbox.io/s/nn9kw2k3ql
这是一个工作示例,您需要按 esc
。
我输入了你的 Profile
没有做任何更改,它也按预期工作。
要清楚...
您可以单击 esc
的红色叠加层将在您进入生产设置后被删除。它们仅供开发使用。这就是为什么您要实施 errorBoundary
的原因,它在两种情况下都适用。
因此,如果您的代码在开发过程中出现错误,这两个错误都会出现。
如果您查看控制台,您会收到以下消息:
false // from ErrorBoundary this.state.error
i am here // inside the potential error componenet
i am here // inside the potential error componenet
The above error occurred in the <Profile> component: //from Error Boundary
true // from ErrorBoundary this.state. error
第一个 false 来自 ErrorBoundary,因为在初始加载时没有错误,所以它会尝试呈现 children
,然后在子项中记录 i am here
。并发现错误,并更新 errorboundary
组件。在那之后,你再也看不到 I am here
,因为 errorboundary
开始并且不再渲染 children
为了让 errorBoundary
知道它的 children
中有一些错误,错误必须首先发生。否则它不知道。 JS是一个动态类型的语言,一切都需要在运行时间内发生。
我认为你的条件错误如下:
if (!hasError) {
return <HasError />
}
如果 hasError 为真,你想在这里显示错误,对吗?否则将呈现 Profile 组件。
而且 componentDidCatch 是在 react16 中构建的,所以如果渲染函数抛出任何错误,这个方法将被自动触发。
正如您在问题中提到的那样,按 Esc
会取消覆盖,您可以看到 ErrorBoundary
消息,并且覆盖的可见性仅限于开发环境。
您可以查看更多相关信息
但是为什么要执行render函数,你需要知道一旦执行了render
函数并且你的代码抛出一个RuntimeError,那是唯一一次componentDidCatch
你的 ErrorBoundary
方法。 create-react-app
还具有一项功能,它可以侦听正在生成的 RuntimeErrors
并报告错误的根本原因,这就是您在叠加层中看到的内容。
查看生成Overlay的相关代码,可以查看这个github code
希望我能回答你的问题。
我使用 React 16
和 Error Boundary
功能:
Profile.js
class Profile extends Component {
constructor(props) {
super(props);
this.state = {
// user: {
// name: "Ha (Huck) H.K. NGUYEN"
// }
user: null
};
this.updateUser = this.updateUser.bind(this);
}
updateUser() {
this.setState({ user: null })
}
render() {
const { user } = this.state;
console.log(user);
return <div className="App">
{user.name}
<button onClick={this.updateUser}>
Update
</button>
</div>
}
}
ErrorBoundary.js
class ErrorBoundary extends Component {
constructor(props) {
super(props);
this.state = {
hasError: false
}
}
componentDidCatch(error, errorInfo) {
this.setState({ hasError: true });
}
render() {
const { children } = this.props;
const { hasError } = this.state;
if (hasError) {
return <HasError />
}
return children
}
}
App.js
class App extends Component {
render() {
return <div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h1 className="App-title">Welcome to React</h1>
</header>
<ErrorBoundary>
<Profile />
</ErrorBoundary>
</div>
}
}
我看到功能组件在错误发生后仍然被调用并被捕获。任何人都可以解释为什么调用 render
函数。
不知道的请按照esc
键可以看到错误边界。
https://codesandbox.io/s/nn9kw2k3ql
这是一个工作示例,您需要按 esc
。
我输入了你的 Profile
没有做任何更改,它也按预期工作。
要清楚...
您可以单击 esc
的红色叠加层将在您进入生产设置后被删除。它们仅供开发使用。这就是为什么您要实施 errorBoundary
的原因,它在两种情况下都适用。
因此,如果您的代码在开发过程中出现错误,这两个错误都会出现。
如果您查看控制台,您会收到以下消息:
false // from ErrorBoundary this.state.error
i am here // inside the potential error componenet
i am here // inside the potential error componenet
The above error occurred in the <Profile> component: //from Error Boundary
true // from ErrorBoundary this.state. error
第一个 false 来自 ErrorBoundary,因为在初始加载时没有错误,所以它会尝试呈现 children
,然后在子项中记录 i am here
。并发现错误,并更新 errorboundary
组件。在那之后,你再也看不到 I am here
,因为 errorboundary
开始并且不再渲染 children
为了让 errorBoundary
知道它的 children
中有一些错误,错误必须首先发生。否则它不知道。 JS是一个动态类型的语言,一切都需要在运行时间内发生。
我认为你的条件错误如下:
if (!hasError) {
return <HasError />
}
如果 hasError 为真,你想在这里显示错误,对吗?否则将呈现 Profile 组件。
而且 componentDidCatch 是在 react16 中构建的,所以如果渲染函数抛出任何错误,这个方法将被自动触发。
正如您在问题中提到的那样,按 Esc
会取消覆盖,您可以看到 ErrorBoundary
消息,并且覆盖的可见性仅限于开发环境。
您可以查看更多相关信息
但是为什么要执行render函数,你需要知道一旦执行了render
函数并且你的代码抛出一个RuntimeError,那是唯一一次componentDidCatch
你的 ErrorBoundary
方法。 create-react-app
还具有一项功能,它可以侦听正在生成的 RuntimeErrors
并报告错误的根本原因,这就是您在叠加层中看到的内容。
查看生成Overlay的相关代码,可以查看这个github code
希望我能回答你的问题。