使用 React Error Boundary 优雅地处理错误
大家好,
在使用 React 开发任何项目时,我们主要处理条件操作或将元素传递给某些组件、函数等。但是,如果 React 组件或函数发生任何意外,并出现运行时错误,大多数情况下你会看到一个死机白屏! 😑 现在,如果你打开开发者工具并检查控制台,你会看到错误。但这绝对不是推荐的处理方式。
这种运行时错误或白屏错误应该得到妥善处理,而这正是React 错误边界 (Error Boundary)应运而生的地方。React 添加了错误边界来捕获 JavaScript 错误并高效处理。根据React 文档,错误边界是一种 React 组件,它可以捕获其子组件树中任何位置的 JavaScript 错误,记录这些错误,并显示回退 UI 而不是崩溃的组件树。截至撰写本文时,React 错误边界仅支持作为类组件。因此,在使用带有钩子的 React 时,这可能是您唯一需要的类组件。
理论讲得够多了,现在让我们深入研究代码——
首先,我们创建一个类组件,并将其用作错误边界。代码如下:
class ErrorBoundary extends Component {
state = {
error: null,
};
static getDerivedStateFromError(error) {
return { error };
}
render() {
const { error } = this.state;
if (error) {
return (
<div>
<p>Seems like an error occured!</p>
<p>{error.message}</p>
</div>
);
}
return this.props.children;
}
}
export default ErrorBoundary;
在上面的代码中,你会看到一个静态方法getDerivedStateFromError(error)
。这个方法会将ErrorBoundary
类组件变成一个实际处理错误的组件。
这里,我们捕获getDerivedStateFromError
方法中的错误并将其设置为状态。如果存在错误,我们会打印它(目前如此);如果没有错误,我们就将控制权返回给原始元素。
现在让我们看看在哪里可以使用这个错误边界。假设你正在打印一个从 API 获取的用户列表。它看起来像这样:
const Users = ({ userData, handleMoreDetails }) => {
return (
<div>
<h1>Users List: </h1>
<ul>
{userData.map((user) => (
<div key={user.id}>
<p>Name: {user.name}</p>
<p>Company: {user.company}</p>
<button onClick={() => handleMoreDetails(user.id)}>
More details
</button>
</div>
))}
</ul>
</div>
);
};
上述user
组件在获取 userData 之前工作正常。但是,如果由于某种原因,userData 为undefined
或null
,我们的应用程序就会崩溃!所以现在,让我们为这个组件添加错误边界。因此,更新后的代码将如下所示:
const Users = ({ userData, handleMoreDetails }) => {
return (
<div>
<h1>Users List: </h1>
<ErrorBoundary>
<ul>
{userData.map((user) => (
<div key={user.id}>
<p>Name: {user.name}</p>
<p>Company: {user.company}</p>
<button onClick={() => handleMoreDetails(user.id)}>
More details
</button>
</div>
))}
</ul>
</ErrorBoundary>
</div>
);
};
在这里,当错误发生时,我们的 ErrorBoundary 组件会捕获该错误,并将错误消息打印到屏幕上。这可以防止应用程序崩溃,并且用户也能了解错误所在。
这里需要考虑的重点是我们使用错误边界的位置。错误边界将显示错误而不是组件。因此,我们始终需要确定错误的位置。在我们的示例中,我们当然希望显示页面标题以及其他详细信息。我们只想替换发生错误的组件,在本例中,它只是ul
元素。因此,我们只将元素包裹ul
在错误边界内,而不是整个组件。
到目前为止,我们已经了解了错误边界是什么以及如何使用它。但是,我们错误边界(显示错误的位置)的回退显示方式尚不完善,可以改进。在同一个应用程序中,不同情况下,错误和回退组件的显示方式会有所不同。因此,我们需要使错误边界组件更加通用,以便所有这些回退 UI 都能使用。
为此,我们将ErrorComponent
在错误边界中创建一个 prop,并在发生错误时返回传递给此 prop 的元素。以下是ErrorBoundary
和User
组件的最终代码:
// User Component
const Users = ({ userData, handleMoreDetails }) => {
const ErrorMsg = (error) => {
return (
<div>
{/* You can use your own styling and methods of handling error */}
<p>Something went wrong!</p>
<p>{error.message}</p>
</div>
);
};
return (
<div>
<h1>Users List: </h1>
<ErrorBoundary ErrorComponent={ErrorMsg}>
<ul>
{userData.map((user) => (
<div key={user.id}>
<p>Name: {user.name}</p>
<p>Company: {user.company}</p>
<button onClick={() => handleMoreDetails(user.id)}>
More details
</button>
</div>
))}
</ul>
</ErrorBoundary>
</div>
);
};
// ErrorBoundary Component
class ErrorBoundary extends Component {
state = {
error: null,
};
static getDerivedStateFromError(error) {
return { error };
}
render() {
const { error } = this.state;
if (error) {
return <this.props.ErrorComponent error={error} />;
}
return this.props.children;
}
}
如果您需要在单个组件中多次使用 key 属性,也可以将其传递给错误边界。这将移除错误边界中先前的错误状态,并在每次渲染时显示正确的元素。
错误边界是 React 非常优秀的功能之一,而且我发现它的使用率相对较低。但在代码中使用它,肯定能让你避免意外错误带来的尴尬时刻。谁不想拥有更好的错误处理呢?😉
如果你不想自己写错误边界组件,有一个很棒的包可以帮你实现。链接:react-error-boundary
以上就是本文的全部内容。请分享您的想法/评论/反馈。如果您喜欢我的文章,也可以在Twitter上联系我,或者请我喝杯咖啡。
继续学习。🙌
文章来源:https://dev.to/hey_yogini/handle-errors-graceously-with-react-error-boundary-25mb