React@16.x(18)错误边界

1,什么是错误边界

默认情况下,如果一个组件在**渲染期间(render)**发生错误,会导致整个组件树被全部卸载。

全部卸载:指整个应用都被卸载,<div id="root"></div> 没有子元素了。
一般此时 React 会在控制台打印错误消息。

举例:

import React, { PureComponent } from "react";

function ChildA() {
    return (
        <>
            <h1>childA</h1>
            <ChildB></ChildB>
        </>
    );
}

function ChildB() {
    const obj = {};
    console.log(obj.a.b);
    return <h1>childB</h1>;
}

function ChildC() {
    return <h1>childC</h1>;
}

export default class App extends PureComponent {
    render() {
        return (
            <>
                <ChildA />
                <ChildC />
            </>
        );
    }
}

错误边界

指的是一个自定义的组件,它可以捕获子组件在渲染期间发生的错误,并有能力阻止继续往上传播。

2,捕获子组件的错误

可以通过2个生命周期函数来捕获。

2.1,static getDerivedStateFromError

2.1.1,特点

1,它是一个静态函数

2,运行时间点:渲染子组件的过程中,发生错误之后,更新页面之前。

3,该函数返回一个对象, React 会用该对象的属性覆盖掉当前组件的 state

不能使用 this.setState(),是因为它是静态函数。

4,通常,该函数用于改变状态。

也就是说,通过改变状态:选择不渲染出错的子组件,而是渲染指定的内容。

2.1.2,举例

新增一个组件

import React, { Component } from "react";

export default class ErroBound extends Component {
    state = {
        hasError: false,
    };

    static getDerivedStateFromError(error) {
        return {
            hasError: true,
        };
    }

    render() {
        if (this.state.hasError) {
            return <div>错误了</div>;
        }
        return this.props.children;
    }
}

修改上面的例子:

export default class App extends PureComponent {
    render() {
        return (
            <>
                <ErroBound>
                    <ChildA></ChildA>
                </ErroBound>
                <ChildC></ChildC>
            </>
        );
    }
}

这样就可以捕获到报错的组件,不影响组件 ChildC 的正常渲染了。

2.2,componentDidCatch

2.2.1,特点

1,实例的方法。

2,运行时间点:渲染子组件的过程中,发生错误更新页面之后。因为时间点靠后,所以不太会在该函数中改变状态(虽然这样使用没有问题。)

3,通常用于记录错误日志进行上报。

2.2.2,举例

// 其他代码不变。
export default class ErroBound extends Component {
    // error 是错误对象。
    // info 是一个多层级的对象,标记报错在哪个组件了。
    componentDidCatch(error, info) {
        this.setState({
            hasError: true,
        });
    }
}

3,错误边界组件无法捕获的错误

3.1,自身的错误

3.2,异步的错误

比如,将 ChildB 组件做如下更改,初次渲染没有问题。1s 之后就会报错。

function ChildB() {
    setTimeout(() => {
        const obj = {};
        console.log(obj.a.b);
    }, 1000);
    return <h1>childB</h1>;
}

3.3,事件中的错误

比如,将 ChildB 组件做如下更改,初次渲染没有问题。点击就会报错。

function ChildB() {
    return (
        <h1
            onClick={() => {
                const obj = {};
                console.log(obj.a.b);
            }}
        >
            childB
        </h1>
    );
}

因为这2个生命周期函数,仅会在首次渲染子组件期间执行,所以异步的错误就捕获不到了。

一句话总结:仅处理子组件渲染期间的同步错误


以上。

  • 15
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

下雪天的夏风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值