ReactJS - static 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) {
      // Log the error here
      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() {
      // Simulate an error
      throw new Error('Error in ChildComponent');
   }
   
   render() {
      return <p>This is a child component</p>;
   }
}

export default App;

輸出

simple error handling 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) {
      // Log the error here
      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,
   };
   
   // Error occur by attempting to load an invalid image
   loadImage = () => {
      const img = new Image();
      img.src = 'image-url1';
      img.onload = () => {
         // This will not execute because the image source is invalid
      };
      img.onerror = () => {
         // Error and catch it in the ErrorBoundary
         this.setState({ hasError: true });
      };
   };   
   componentDidMount() {
      this.loadImage();
   }
   
   render() {
      if (this.state.hasError) {
         // Render an alternative content when an error occurs
         return <p>Failed to load the image</p>;
      }
      
      return <img src="image-url2" alt="A Valid Image" />;
   }
}

export default App;

輸出

error handling with images

在此示例中,`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) {
      // Log the error here
      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() {
      // Error by trying to fetch data from an invalid API endpoint
      fetch('https://invalid-api-endpoint')
      .then((response) => response.json())
      .then((data) => this.setState({ data }))
      .catch((error) => {
      // Error and catch it in the 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;

輸出

error handling with api fetch

限制

  • `getDerivedStateFromError` 應該是一個沒有副作用的純函式。如果我們必須執行諸如呼叫分析服務之類的活動,我們也應該使用 `componentDidCatch`。

  • 在使用函式元件時,`getDerivedStateFromError` 沒有直接等效項。為了提供類似的功能,我們可以構建單個 ErrorBoundary 元件或使用諸如 `react-error-boundary` 之類的包。

總結

理解 `getDerivedStateFromError` 對於正確管理 React 應用中的錯誤至關重要。透過將此方法納入您的錯誤處理策略,您可以透過顯示有用的錯誤訊息而不是令人困惑的 UI 問題來提供更好的使用者體驗。

reactjs_reference_api.htm
廣告