使用 React Error Boundary 优雅地处理错误

2025-05-28

使用 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;

Enter fullscreen mode Exit fullscreen mode

在上面的代码中,你会看到一个静态方法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>
    );
};
Enter fullscreen mode Exit fullscreen mode

上述user组件在获取 userData 之前工作正常。但是,如果由于某种原因,userData 为undefinednull,我们的应用程序就会崩溃!所以现在,让我们为这个组件添加错误边界。因此,更新后的代码将如下所示:



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>
    );
};


Enter fullscreen mode Exit fullscreen mode

在这里,当错误发生时,我们的 ErrorBoundary 组件会捕获该错误,并将错误消息打印到屏幕上。这可以防止应用程序崩溃,并且用户也能了解错误所在。

这里需要考虑的重点是我们使用错误边界的位置。错误边界将显示错误而不是组件。因此,我们始终需要确定错误的位置。在我们的示例中,我们当然希望显示页面标题以及其他详细信息。我们只想替换发生错误的组件,在本例中,它只是ul元素。因此,我们只将元素包裹ul在错误边界内,而不是整个组件。

到目前为止,我们已经了解了错误边界是什么以及如何使用它。但是,我们错误边界(显示错误的位置)的回退显示方式尚不完善,可以改进。在同一个应用程序中,不同情况下,错误和回退组件的显示方式会有所不同。因此,我们需要使错误边界组件更加通用,以便所有这些回退 UI 都能使用。

为此,我们将ErrorComponent在错误边界中创建一个 prop,并在发生错误时返回传递给此 prop 的元素。以下是ErrorBoundaryUser组件的最终代码:

// 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>
    );
};
Enter fullscreen mode Exit fullscreen mode
// 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;
    }
}
Enter fullscreen mode Exit fullscreen mode

如果您需要在单个组件中多次使用 key 属性,也可以将其传递给错误边界。这将移除错误边界中先前的错误状态,并在每次渲染时显示正确的元素。

错误边界是 React 非常优秀的功能之一,而且我发现它的使用率相对较低。但在代码中使用它,肯定能让你避免意外错误带来的尴尬时刻。谁不想拥有更好的错误处理呢?😉

如果你不想自己写错误边界组件,有一个很棒的包可以帮你实现。链接:react-error-boundary

以上就是本文的全部内容。请分享您的想法/评论/反馈。如果您喜欢我的文章,也可以在Twitter上联系我,或者请我喝杯咖啡

继续学习。🙌

文章来源:https://dev.to/hey_yogini/handle-errors-graceously-with-react-error-boundary-25mb
PREV
你用错了表情符号 从示例开始 问题 为什么会出现这种情况? 解决方法 注意事项 结论
NEXT
从 create-react-app 迁移到 Vite:快速简易指南