ReactJS - 静态 getDerivedStateFromError() 方法
当组件或其子组件在 React 中呈现时遇到错误时,处理和向用户传达该错误可能很困难。getDerivedStateFromError 函数在这里发挥作用。在本教程中,我们将了解它的工作原理。
在 React 中,我们可以在类组件中定义一个名为 getDerivedStateFromError 的特定函数。当子组件(无论其层次结构有多深)遇到错误时,React 都会调用此函数。我们可以显示详细的错误消息,而不是显示空白或损坏的用户界面。
语法
static getDerivedStateFromError(error)
参数
error − getDerivedStateFromError 中的 error 参数提供错误信息。它通常是一个 Error 实例,但也可以是其他类型。
返回值
该方法应返回更新后的状态,表明组件应显示错误消息。
示例
示例 1
创建使用 getDerivedStateFromError 函数的基本 React 应用需要创建一个具有错误限制的简单类组件。下面是一个使用 getDerivedStateFromError() 函数的小示例 −
import React, { Component } from 'react'; class ErrorBoundary extends Component { constructor(props) { super(props); this.state = { hasError: false, errorMessage: '' }; } static getDerivedStateFromError(error) { return { hasError: true, errorMessage: error.message }; } componentDidCatch(error, errorInfo) { // 在这里记录错误 console.error(error, errorInfo); } render() { if (this.state.hasError) { return ( <div> <h2>Something went wrong</h2> <p>{this.state.errorMessage}</p> </div> ); } return this.props.children; } } class App extends Component { render() { return ( <div> <h1>Simple Error Handling App</h1> <ErrorBoundary> {/* error in a child component */} <ChildComponent /> </ErrorBoundary> </div> ); } } class ChildComponent extends Component { componentDidMount() { // 模拟错误 throw new Error('Error in ChildComponent'); } render() { return <p>This is a child component</p>; } } export default App;
输出

此示例展示了如何使用使用 getDerivedStateFromError 和 componentDidCatch 函数的 ErrorBoundary 类组件制作一个简单的 React 应用程序。为了展示错误处理,ChildComponent 在其 componentDidMount 生命周期函数中故意抛出错误。
当我们启动应用程序时,我们将在用户界面中收到一条错误消息。我们可以修改和扩展此代码以满足我们自己的要求。
示例 2
这是另一个借助 React 组件中的 getDerivedStateFromError 函数进行错误处理的示例。这次,我们将在渲染图像的子组件中模拟错误 −
import React, { Component } from 'react'; import './App.css'; class ErrorBoundary extends Component { constructor(props) { super(props); this.state = { hasError: false, errorMessage: '' }; } static getDerivedStateFromError(error) { return { hasError: true, errorMessage: error.message }; } componentDidCatch(error, errorInfo) { // 在这里记录错误 console.error(error, errorInfo); } render() { if (this.state.hasError) { return ( <div> <h2>Something went wrong</h2> <p>{this.state.errorMessage}</p> </div> ); } return this.props.children; } } class App extends Component { render() { return ( <div className='App'> <h1>Error Handling with Images</h1> <ErrorBoundary> {/* error in a child component */} <ImageComponent /> </ErrorBoundary> </div> ); } } class ImageComponent extends Component { state = { hasError: false, }; // 尝试加载无效图像时发生错误 loadImage = () => { const img = new Image(); img.src = 'image-url1'; img.onload = () => { // 由于图像源无效,因此不会执行此操作 }; img.onerror = () => { // 错误并在 ErrorBoundary 中捕获它 this.setState({ hasError: true }); }; }; componentDidMount() { this.loadImage(); } render() { if (this.state.hasError) { // 发生错误时呈现替代内容 return <p>Failed to load the image</p>; } return <img src="image-url2" alt="A Valid Image" />; } } export default App;
输出

在此示例中,ImageComponent 组件尝试加载具有无效 URL 的图像,这会触发错误。ErrorBoundary 会捕获该错误,我们可以自定义发生错误时组件的渲染。
示例 3
在此示例中,我们将在从 API 获取数据的子组件中创建一个错误。getDerivedStateFromError 函数将用于管理错误并显示用户友好的消息。代码如下 −
import React, { Component } from 'react'; import './App.css'; class ErrorBoundary extends Component { constructor(props) { super(props); this.state = { hasError: false, errorMessage: '' }; } static getDerivedStateFromError(error) { return { hasError: true, errorMessage: error.message }; } componentDidCatch(error, errorInfo) { // 在这里记录错误 console.error(error, errorInfo); } render() { if (this.state.hasError) { return ( <div> <h2>Something went wrong</h2> <p>{this.state.errorMessage}</p> </div> ); } return this.props.children; } } class App extends Component { render() { return ( <div> <h1>Error Handling with API Fetch</h1> <ErrorBoundary> {/* error in a child component */} <ApiDataComponent /> </ErrorBoundary> </div> ); } } class ApiDataComponent extends Component { state = { data: null, }; componentDidMount() { // 尝试从无效的 API 端点获取数据时出错 fetch('https://invalid-api-endpoint') .then((response) => response.json()) .then((data) => this.setState({ data })) .catch((error) => { // 错误并在 ErrorBoundary 中捕获它 throw new Error('Error fetching data from the API'); }); } render() { return ( <div className='App'> <h3>API Data</h3> {this.state.data ? ( <ul> {this.state.data.map((item) => ( <li key={item.id}>{item.name}</li> ))} </ul> ) : ( <p>Loading data...</p> )} </div> ); } } export default App;
输出

限制
getDerivedStateFromError 应该是一个没有副作用的纯函数。如果我们必须执行诸如调用分析服务之类的活动,我们还应该使用 componentDidCatch。
使用函数组件时,getDerivedStateFromError 没有直接等效项。为了提供类似的功能,我们可以构造单个 ErrorBoundary 组件或使用 react-error-boundary 之类的包。
摘要
了解 getDerivedStateFromError 对于正确管理 React 应用程序中的错误至关重要。如果将此方法纳入您的错误处理策略中,您可以通过显示有用的错误消息而不是令人困惑的 UI 问题来提供更好的用户体验。