错误边界(Error boundaries)
从react v16开始,引入边界错误概念。
核心API
getDerivedStateFromError
componentDidCatch
1. 目的:某些UI崩溃,不至于整个webapp崩溃
2. 注意⚠️:错误边界无法捕获如下场景的错误
- 事件处理(了解更多)
- 异步代码(例如
setTimeout
或requestAnimationFrame
回调函数) - 服务端渲染
- 它自身抛出来的错误(并非它的子组件)
3.编写错误边界组件
import React, { Component } from 'react';interface ErrorBoundaryProps { };interface ErrorBoundaryState { hasError: boolean;};class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> { constructor(props: ErrorBoundaryProps) { super(props); this.state = { hasError: false }; } static getDerivedStateFromError(error: Error) { // 更新 state 使下一次渲染能够显示降级后的 UI return { hasError: true }; } componentDidCatch(error: Error, errorInfo: React.ErrorInfo) { // 你同样可以将错误日志上报给服务器 console.group(); console.log('ErrorBoundary catch a error:'); console.info('error', error); console.info('error info', errorInfo); console.groupEnd() } render() { console.log('component ErrorBoundary render...'); const { children } = this.props; const { hasError } = this.state; // return ( // <> // { // hasError ? 'Something Wrong' : children // } // </> // ) if (hasError) { return 'Something wrong'; } else { return children; } }}export default ErrorBoundary;
4.编写一个“错误组件”
点击按钮,触发+1,当counter为5时,抛出Error
import React, { Component } from 'react';interface ErrorComponentProps { };interface ErrorComponentState { counter: number;};class ErrorComponent extends Component<ErrorComponentProps, ErrorComponentState> { constructor(props: any) { super(props); this.state = { counter: 0 } this.handleClick = this.handleClick.bind(this); } handleClick() { // 事件处理的错误,ErrorBoundary无法捕捉 // if (this.state.counter === 5) { // throw new Error(); // } this.setState({ counter: this.state.counter + 1 }); } render() { console.log('component ErrorComponent render...'); const { counter } = this.state; const { handleClick } = this; if (counter === 5) { throw new Error('counter creashed!'); } return ( <> <p>this component will throw Error when the counter equal to 5</p> <p>counter : {counter}</p> <button onClick={handleClick}>add</button> </> ) }}export default ErrorComponent;
5. 组合
import React from 'react';import ErrorBoundary from './component/ErrorBoundary';import ErrorComponent from './component/ErrorBoundary/ErrorComponent';function App() { return ( <div className="App"> <ErrorBoundary> <ErrorComponent /> </ErrorBoundary> </div> );}export default App;
6.打包静态资源
> 不再devserver测试的原因是,在cra的配置中,webpack会捕捉Error并显示错误蒙版,不便于看到测试结果
在package.json添加字段"homepage": "."