React.js |錯誤邊界


前言:做筆記,參考:react文檔,文章涉及的示例:https://sanhuamao1.coding.net/public/note/myapp/git/files/13Error-Boundaries

錯誤邊界

錯誤邊界是一種 React 組件,可以捕獲並打印發生在其子組件樹任何位置的 JavaScript 錯誤,並且渲染出備用 UI。錯誤邊界在渲染期間、生命周期和整個組件樹的構造函數中捕獲錯誤。

它無法在以下場景捕獲錯誤:

  • 事件處理(了解更多)
  • 異步代碼(例如 setTimeout 或 requestAnimationFrame 回調函數)
  • 服務端渲染
  • 它自身拋出來的錯誤(並非它的子組件)

使用方式

這是兩種生命周期方法。只要class組件用了任意一種,那它就變成一個錯誤邊界組件


方式一:componentDidCatch()

class ErrorBoundary extends React.Component {
    constructor(props) {
      super(props);
      this.state = { hasError: false };
    }
    componentDidCatch(error, errorInfo) {
      this.setState({
          error:error,
          errorInfo:errorInfo
      })
    }
    render() {
      if (this.state.errorInfo) {
        return <div>
            {this.state.error&&this.state.error.toString()}<br/> {this.state.errorInfo.componentStack}
        </div>
        
      }
      //正常則返回子元素,即該組件包裹的元素
      return this.props.children; 
    }
 }

一個測試組件,如果輸入的是非字母就會報錯:

class Example extends React.Component{
    constructor(props){
        super(props)
        this.state={value:""}
        this.handleChange=(e)=>{
            this.setState({value:e.target.value})
        }
    }
    render(){
        const value=this.state.value
        if(/^[a-zA-Z]+$/.test(value)||value===""){
            return  <input type="text" onChange={this.handleChange} placeholder="只能填字母"/>
        }
        throw new Error('出錯了!');
    }
}

App.js

<ErrorBoundary>
   <Example />
</ErrorBoundary>

方式二:static getDerivedStateFromError()

class ErrorBoundary extends React.Component {
    constructor(props) {
      super(props);
      this.state = { hasError: false };
    }
    static getDerivedStateFromError(error) {
      return { hasError: true };
    }
    
    render() {
      if (this.state.hasError) {
        //顯示降級UI
        return <div>出錯了bro!</div>
      }
      return this.props.children; 
    }
 }

image.png


你也可以同時使用兩種。

看樣子componentDidCatch()好像沒什么用,因為一般情況下瀏覽器會告訴你只能在控制台看錯誤日志,並且在沒有使用該錯誤邊界組件的情況下,控制台也會打印出同樣的錯誤信息。相比之下,能渲染出備用組件的static getDerivedStateFromError()的實用性高一點。其實,無論使用哪一種,它都起到了創建錯誤邊界組件的作用。

錯誤邊界組件的工作方式類似於 JavaScript 的 catch {},不同之處在於它只針對 React 組件。且只有 class 組件才可以成為錯誤邊界組件。注意,它無法捕獲其自身的錯誤。

如果沒有使用錯誤邊界會怎樣?

自 React 16 起,任何未被錯誤邊界捕獲的錯誤將會導致整個 React 組件樹被卸載。

經驗告訴我們,完全移除比保留錯誤UI更好。例如,在類似 Messenger 的產品中,把異常的 UI 展示給用戶可能會導致用戶將信息錯發給別人。

增加錯誤邊界能夠讓你在應用發生異常時提供更好的用戶體驗。例如,Facebook Messenger 將側邊欄、信息面板、聊天記錄以及信息輸入框包裝在單獨的錯誤邊界中。如果其中的某些 UI 組件崩潰,其余部分仍然能夠交互。

try/catch的缺陷

try / catch 很棒但它僅能用於命令式代碼:

try {
  showButton();
} catch (error) {
  // ...
}

然而,React 組件是聲明式,並且具體指出 什么 需要被渲染:

<Button />

為什么無法捕獲事件處理器的內部錯誤?

React 不需要錯誤邊界來捕獲事件處理器中的錯誤。與 render 方法和生命周期方法不同,事件處理器不會在渲染期間觸發。因此,如果它們拋出異常,React 仍然能夠知道需要在屏幕上顯示什么。如果你需要在事件處理器內部捕獲錯誤,使用普通的 JavaScript try / catch 語句:

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { error: null };
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    try {
      // 執行操作,如有錯誤則會拋出
    } catch (error) {
      this.setState({ error });
    }
  }

  render() {
    if (this.state.error) {
      return <h1>捕獲到一個錯誤</h1>
    }
    return <button onClick={this.handleClick}>點擊</button>
  }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM