react系列(20)错误边界:异常捕获

部分 UI 的异常不应该破坏了整个应用。为了解决 React 用户的这一问题,React 16 引入了一种称为 “错误边界” 的新概念。错误边界是用于捕获其子组件树 JavaScript 异常,记录错误并展示一个回退的 UI 的 React 组件,而不是整个组件树的异常。错误组件在渲染期间,生命周期方法内,以及整个组件树构造函数内捕获错误。

错误边界通过componentDidCatch() 方法机来捕获异常,制类似于 JavaScript catch {},但记住,仅有类组件可以成为错误边界。如果一个错误边界无法渲染错误信息,则错误会向上冒泡至最接近的错误边界。这也类似于 JavaScript 中 catch {} 的工作机制。下面是一个错误边界的例子:

定义一个错误边界捕获的类ErrorBoundary.jsx:

import React from 'react';

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

	componentDidCatch(error, info) {
		this.setState({
			hasError: true,
			error: error
		});
		console.log("ErrorBoundary!!!");
	}

	render() {
		if(this.state.hasError) {
			return <h1>{this.state.error.toString()}</h1>;
		}
		return this.props.children;
	}
}

//导出组件
export default ErrorBoundary;

触发错误边界的组件ErrorDemo.jsx:

import React from 'react';

class ErrorDemo extends React.Component {
	constructor(props) {
		super(props);
		this.state = {};
	}

	render() {
		throw new Error('I crashed!');
		return(
			<div>No Error</div>
		);
	}
}

export default ErrorDemo;

渲染组件及错误边界用法:

import React from 'react';
import ErrorDemo from './components/errorboundary/ErrorDemo.jsx';
import ErrorBoundary from './components/errorboundary/ErrorBoundary.jsx'; 

class App extends React.Component {
	constructor(props) {
		super(props);
		this.state = {};
	}

	render() {
		return(
			<ErrorBoundary>
				<ErrorDemo />
			</ErrorBoundary>
		);
	}
}

export default App;

此时发现在生产环境下,虽然会打印错误,但不影响程序继续正常运行,但如果在开发环境,页面依然会报错。

在最新的官方代码中,新增了静态方法getDerivedStateFromError用来改变ErrorBoundary.js的hasError状态,而方法componentDidCatch只用于打印错误日志,新的ErrorBoundary.js写法如下:

import React from 'react';

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

    static getDerivedStateFromError(error) {
        // 更新 state 使下一次渲染能够显示降级后的 UI
        return { hasError: true, error: error };
    }

    componentDidCatch(error, info) {
        // 打印错误日志
        console.log('ErrorBoundary:', error, info);
    }

    render() {
        if (this.state.hasError) {
            return <h1>{this.state.error.toString()}</h1>;
        } else {
            return this.props.children;
        }
    }
}

//导出组件
export default ErrorBoundary;

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值