有效的错误管理对于构建弹性和用户友好的 React 应用程序至关重要。当您的应用程序遇到意外错误时,必须提供一种优雅的方式来处理这些错误并将其呈现给用户,同时保持其功能不变。React 的错误边界(Error Boundaries)为实现这一目标提供了强大的机制,本文将探讨它们是什么、如何实现它们以及它们的最佳实践。
React 错误边界就像应用程序的安全网。当树状结构中的任何组件发生错误时,这些边界会捕获错误,防止整个应用程序崩溃。它们提供了一种显示回退 UI 和记录错误详细信息的方法,让您可以更优雅地处理错误。这是一个很好的工具,可以增强用户体验,帮助开发人员在不中断整个应用程序的情况下发现并解决问题。纳入错误边界是提高前端稳定性的明智之举。
为什么错误边界对 React 应用程序很重要?
如果没有错误边界,组件中的一个错误就有可能导致整个应用程序瘫痪,造成令人沮丧的用户体验,并使开发人员难以确定根本原因。错误边界对 React 应用程序非常重要,原因有以下几点:
- 防止应用程序崩溃:错误边界可捕获其组件树中的错误,防止错误在组件层次结构中向上传播,导致整个应用程序崩溃。这样,即使发生错误,也能确保更稳定、响应更快的用户体验。
- 改善用户体验:错误边界不会使应用程序突然崩溃,而是会显示一个后备用户界面,告知用户错误并提供更可控的响应。这可以防止用户产生挫败感,并允许他们继续与应用程序进行交互。
- 隔离错误:错误边界有助于将错误隔离到特定组件,从而更容易识别和调试问题的根源。这简化了开发流程,减少了调试时间,因为开发人员可以专注于发生错误的特定组件。
- 记录错误:错误边界可用于将错误记录到外部服务或分析平台。这能为应用程序行为和潜在问题提供有价值的见解,帮助开发人员识别模式、跟踪错误发生情况并确定调试工作的优先级。
- 可维护代码:错误边界将错误处理逻辑封装在特定组件中,从而提高了代码的可维护性。这样就更容易理解和修改错误处理行为,而不会影响应用程序的其他部分。
- 优雅的错误处理:错误边界可实现优雅的错误处理,使开发人员能够向用户提供有意义的反馈,并在发生错误时保持一致的用户体验。这将提升整体用户体验,并建立对应用程序的信任。
总之,错误边界在确保 React 应用程序的稳定性和可用性方面发挥着至关重要的作用。它们可以防止意外崩溃,改善用户体验,简化调试,并提供有关应用程序行为的宝贵见解。
React 应用程序中错误边界的实际实现
在本节中,我们将深入探讨错误边界的工作原理,将复杂的问题分解为简单的部分。我们将构建一个 React 应用程序,创建一个错误边界组件。通过用这个保护层包裹我们的组件,我们就能加强应用程序的抗错能力,确保更流畅的用户体验。
如何创建错误边界组件
错误边界组件是一种特殊的 React 组件,可以捕捉其子组件中发生的错误。这样,您就可以显示一个后备 UI,而不是让整个应用程序崩溃。在 React 中,错误边界必须是类组件,因为它们依赖于只有类组件才能使用的两个特定生命周期方法。请注意,功能组件不能使用这些生命周期方法,因此它们不能成为错误边界。
要创建错误边界组件,您需要创建一个类组件,并实现以下生命周期方法中的一个或两个:
static getDerivedStateFromError()
:该方法可在出错后渲染回退用户界面。componentDidCatch()
:该方法将错误信息记录到控制台或错误报告服务中。
首先创建一个新组件 ErrorBoundary.js,作为错误边界。该组件需要定义生命周期方法:static getDerivedStateFromError() 和 componentDidCatch()。
import React, { Component } from 'react'; class ErrorBoundary extends Component { constructor(props) { super(props); this.state = { hasError: false }; } static getDerivedStateFromError(error) { return { hasError: true }; } componentDidCatch(error, errorInfo) { // You can log the error console.error('Error:', error); console.error('Error Info:', errorInfo); } render() { if (this.state.hasError) { return (); } return this.props.children; } } export default ErrorBoundary;Something went wrong. Please try again later.
上述代码定义了一个名为 ErrorBoundary 的 React 组件,旨在捕捉其子组件中的错误。让我们来分解代码:
- 导入语句:
import React, { Component } from 'react';
这一行从 react
库中导入 React 对象和 Component 类。在 React 中创建类组件需要使用 Component 类。
- 类定义:
class ErrorBoundary extends Component {
这里定义了一个名为 ErrorBoundary
的类,它扩展了 Component 类。这意味着 ErrorBoundary
是一个 React 类组件。
- 构造函数:
constructor(props) { super(props); this.state = { hasError: false }; }
constructor
方法用于初始化组件的状态。在本例中,它将初始状态设置为 hasError
,并将属性设置为 false
。要调用父类(Component
)的构造函数,就必须调用 super(props)
。
- 静态方法 –
getDerivedStateFromError
:
static getDerivedStateFromError(error) { return { hasError: true }; }
此静态方法是 React 16 中引入的生命周期方法。它在渲染过程中发生错误时被调用,其目的是根据发生的错误更新组件状态。在这种情况下,它会将 hasError
设为 true
。
- 方法 – componentDidCatch:
componentDidCatch(error, errorInfo) { console.error('Error:', error); console.error('Error Info:', errorInfo); }
componentDidCatch
是另一个生命周期方法,在渲染过程中出现错误后被调用。它提供了一个记录错误详细信息的机会。在本例中,它会将错误和错误信息记录到控制台。
- 渲染方法:
render() { if (this.state.hasError) { return (); } return this.props.children; }Something went wrong. Please try again later.
render
方法负责渲染组件。如果 hasError
为 true
,它会返回一个表示出错的后备 UI。否则,它会渲染子组件( this.props.children
),当没有错误时,允许正常渲染组件的子组件。
- 导出声明:
export default ErrorBoundary;
这一行导出 ErrorBoundary
组件,使其可用于其他应用部分。
总之,ErrorBoundary
组件将被用作其他组件的包装器。如果被封装的组件发生任何错误, ErrorBoundary
将捕捉错误、更新其状态、记录错误细节,并渲染一个后备用户界面来通知用户出错了。
如何使用错误边界组件
要使用错误边界组件,请将其包裹在要捕捉错误的组件周围。在此之前,我们将更新错误边界组件中的后备用户界面,以显示更合适的信息。
// ErrorBoundary.js import React, { Component } from "react"; class ErrorBoundary extends Component { constructor(props) { super(props); this.state = { hasError: false }; } static getDerivedStateFromError(error) { return { hasError: true }; } componentDidCatch(error, errorInfo) { this.setState({ error: error, errorInfo: errorInfo, hasError: true, }); } render() { if (this.state.hasError) { return (); } return this.props.children; } } export default ErrorBoundary;Oops! Something went wrong.
This is not a car.
如果在 ErrorBoundary
范围内发生任何错误,它将捕捉错误、更新状态并呈现用户友好的消息,而不是让整个应用程序崩溃。
现在,我们将创建一个组件,并将其命名为 Carsection
。在 CarSection
组件中,我们将使用 throw new Error 语句在特定条件下生成错误。在本例中,如果传递给组件的 carName
prop 等于 Airbus
,就会触发错误,提示信息为 not a car
import React from 'react'; const CarSection = ({carName}) => { if (carName === 'Airbus') { throw new Error('not a car') } return ({carName}); }; export default CarSection;
从本质上讲, CarSection
组件的设计目的是根据 carName
prop 的值有条件地抛出错误,展示了如何在 React 应用程序中实现错误边界来管理错误。
下一步是在 App.js
组件中使用 ErrorBoundary
组件封装可能会出错的组件或代码。
当 CarSection
组件接收到值为 “Airbus” 的 carName
命题时,它会使用 throw new Error('not a car')
触发一个错误。然后,ErrorBoundary
组件会捕捉到这个错误,并显示其 errorMessage
prop 中指定的信息。在本例中, ErrorBoundary
被设置为显示 “Not a car” 作为错误信息。因此,当 CarSection
组件接收到 ” Airbus
” 时,用户界面将显示 “Not a car” 的错误信息。
错误边界的局限性
虽然 React 中的错误边界是处理组件中错误的强大工具,但仍有一些限制和注意事项需要了解:
- 异步代码:异步代码(如
setTimeout
或网络请求)中的错误不会被错误边界捕获,因为它们发生在常规组件生命周期之外。 - 无法捕捉事件处理程序中的错误:错误边界在呈现阶段工作,因此不会捕获事件处理程序或异步代码中出现的错误。
- 错误边界本身中的错误:如果错误发生在错误边界自身的
render
、componentDidCatch
或构造函数方法中,错误边界将不会捕获这些错误。这可能会导致错误边界本身失效。 - 服务器端渲染: 错误边界不是为捕获服务器端渲染过程中发生的错误而设计的。它们在客户端的 React 应用程序中效果最佳。
尽管存在这些局限性,错误边界仍然是一种有价值的工具,它可以防止崩溃,并在错误发生时提供更好的用户体验,从而提高应用程序的健壮性。
小结
在本指南中,我们探讨了 React 中错误边界的概念,了解了它们在类组件的呈现阶段和生命周期方法中捕获错误的作用。我们深入研究了它们的用法,设置它们以创建后备用户界面,并讨论了它们的局限性。
错误边界提供了一种强大的机制,可以防止可怕的白屏死机,并增强 React 应用程序的弹性。通过在组件层次结构中战略性地放置错误边界,开发人员可以拦截错误、显示用户友好的消息并保持更流畅的用户体验。
总之,掌握了错误边界的实现方法,React 开发人员就能创建更强大的应用程序,优雅地处理错误,确保更有弹性和用户友好的网络体验。
了解更多关于 React 错误的处理办法:
- 如何修复React报错 – TypeError: Cannot Read Property ‘Map' of Undefined
- 如何在React中修复 “JSX表达式必须有一个父元素” 的问题
- 如何修复React中的 “‘Switch' is not exported from ‘react-router-dom' ” 错误
- 如何修复 “React Hook useEffect Has a Missing Dependency” 错误
- 如何修复 “React Must Be in Scope When Using JSX” 错误
原文地址:https://www.wbolt.com/a-guide-to-error-boundaries.html