Re: 新手让网页 act 起来: Day28 - Error boundary

前言

在开发的过程中,难免会有些疏失而导致程序出现错误,最终画面呈现一片空白。而在 React 中,我们可以利用 Error boundary (错误边界) ,来帮助我们呈现错误例外的画面,今天就让我们来学习如何使用 Error boundary 吧!

Error boundary

Error boundary 是一个 React Class Component,它能够捕捉底下被包覆的子元件所抛出的错误,并且渲染事先定义好的预备画面。透过这样的机制,当发生错误被抛出来的时候,我们的 UI 不会因为错误而整个坏掉。接下来就让我们来看看使用范例吧!

假设我们有一个文章区块,当按下 See more 的时候,会发生错误,导致整个 App 停止运作,在正式的环境下会直接变成全白,而在开发环境 React 会跳出错误来。

//App.js
import React from 'react'
import Post from './components/Post.js'
import './css/App.css'


function App() {
  return (
    <div className="App">
      <h1>My post:</h1>
      <Post />
    </div>
  );
}

export default App;
//Post.js
import React, { useState } from 'react'
import '../css/Post.css'

const fetchData = () => new Promise((_, reject)=>{
  setTimeout(()=>{
    reject('faild to get data')
  }, 2000)
})

export function Post(){
  const [postData, setPostData] = useState({
    reqStatus: 'idle',
    content: 'Lorem ipsum dolor sit amet consectetur adipisicing elit. Iste facilis voluptas quis possimus reiciendis ducimus ab est quo nisi hic cumque officia dicta magni harum, ipsa accusantium eum culpa vel!...',
    error: null
  })
  const { reqStatus, content, error } = postData

  function clickHandler(){
    setPostData(prev => ({...prev, reqStatus: 'pending'}))
    fetchData()
      .then((res)=>{
        setPostData(prev => ({
          ...prev,
          reqStatus: 'successed',
          content: res.data
         }))
      })
      .catch(error => {
        setPostData(prev => ({
          ...prev,
          reqStatus: 'failed',
          error
         }))
      })
  }

  if(reqStatus === 'failed'){
    throw error
  }

  return(
    <div className='post-container'>
      <h2>How to use Error boundary ?</h2>
      <p>
        { reqStatus === 'pending' ?  'Loading....' : content }
      </p>
      <button onClick={clickHandler}>See more</button>
    </div>
  )
}

export default Post

production

development

这个时候我们就能使用 Error boundary 来帮助我们!

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { error: null, errorInfo: null};
  }

  componentDidCatch(error, errorInfo) {
    this.setState({
      error,
      errorInfo
    })
  }

  render() {
    if (this.state.errorInfo) {
 
      return (
        <div>
          <h2>Something went wrong.</h2>
          <details style={{ whiteSpace: 'pre-wrap' }}>
            {this.state.error && this.state.error.toString()}
            <br />
            {this.state.errorInfo.componentStack}
          </details>
        </div>
      );
    }
 
    return this.props.children;
  }
}

在我们的 Error boundary 元件中,componentDidCatch 这个方法会接住底下任何子元件所抛出的错误以及抛出错误的地方。所以,我们在 render 方法中,可以透过 error 的 state 判断要不要 render 底下的元件,或是我们的错误资讯。

react-error-boundary

如果觉得自己写一个 class component 很麻烦,我们也可以使用 react-error-boundary 这个套件,接下来让我们就来使用它来改写上面的范例吧!

  1. 先安装 react-error-boundary
yarn add react-error-boundary
  1. 引入 ErrorBoundary
import { ErrorBoundary } from 'react-error-boundary'
  1. 定义 ErrorFallback 元件
  function ErrorFallback({ error, resetErrorBoundary  }) {
    return (
      <div>
        <p>Something went wrong:</p>
        <pre>{error}</pre>
        <button onClick={resetErrorBoundary}>Try again</button>
      </div>
    );
  }
  1. 在 ErrorBoundary 元件中的 FallbackComponent 属性挂上 ErrorFallback
function App() {
  return (
    <div className="App">
      <h1>My post:</h1>
      <ErrorBoundary
        FallbackComponent={ErrorFallback}
      >
        <Post />
      </ErrorBoundary>
    </div>
  );
}

这样我们就顺利的改写成功了!关於 react-error-boundary 还有其他方便的方法可以使用,有兴趣的朋友可以到它的 github 再做研究,以上就是今天的分享,如果有任何问题都欢迎在下方留言!

该文章同步发布於:我的部落格


<<:  【DAY 29】Microsoft 365 X Dynamic 365该怎麽选才好呢? (下)

>>:  【Day28-爬虫】资料分析有时候还是需要自己生资料的——以python自动抓取gif梗图为例,十分钟简单上手爬虫(含范例程序)

Day[-2] 今天我想来点Kibana的Data Table

这个Data Table有点像是excel枢纽表的概念 做成一个表格形式来呈现你的资料 选Data ...

Day26-useCallback

前言 在昨天我们学会使用memo去记忆我们的组件,达成避免re-render的状态。 而我们今天会学...

DAY 10 『 UIAlertController 』Part1

从中间弹出的 Alert style: .default => 按钮字体颜色为预设的蓝色 ha...

Day1.认识GUI和Tkinter

图形使用者介面(Graphical User Interface,GUI) 指透过点击图示执行隐含的...

拿 ml5 来练习 p5.js (二)

介绍 首先介绍什麽是 p5.js, p5.js 是基於 Processing 在浏览器中提供友善的画...