关于Warning: setState(...): Can only update a mounted or mounting component.的解决方案

一、原因

在做项目的时候,控制台一直报一个错误。最初以为是脏数据导致的key重复问题,后来发现这个问题一直存在。细看,发现具体错误提示如下:
错误描述

略经思考,脑子里首先闪现的问题原因是,setState异步函数在组件生命周期结束后异步抛出。经此设想,快速切换两个路由,此问题复现,即证明了猜想是正确的。

react中快速切换路由时报此错误,是由于在组件开始挂载(componentWillmount)或者组件挂载之后(componentDidmount)进行了异步操作,比如ajax请求或者setState操作、定时器等。当进行快速切换路由操作的时候,组件已经卸载(unmounted),此时setState等异步操作中的callback回调执行时没有值,从而抛出报错。

二、解决方法

1.在组件挂载时需要进行异步操作的组件封装为公共组件

满足业务场景的情况下,将此异步操作封装在最外层的公共组件中,这样就不会出现所谓的组件卸载情况。但是,这种方法明显不满足所有业务场景,而且提升为公共组件也可能造成不必要的重复渲染。

2. 重写setState()函数

这种方法基本能满足所有使用场景。当组件卸载时就会执行该方法,当组件重新挂载时会继承父组件的setState方法,从而不影响页面的渲染。

不过该方法也存在弊端,在集成的子组件中能修改父组件的setState方法,只是在javascript的语法中很适用,所以最好只在出现此bug的页面中使用。

componentWillUnmount = () => {
    this.setState = (state,callback)=>{
      return;
    };
}
3.结合flag使用异步操作
componentDidMount = () => {
    this._flag = true;
    $.ajax('请求接口',{})
        .then(res => {
            if(this._flag){
                this.setState({
                    pageState:true
                })
            }
        })
        .catch(err => {})
}
componentWillUnMount = () => {
    this._flag = false;
}
4.在卸载的时候对所有的操作进行清除(推荐)

当我们使用异步操作的时候,往往会忽略后续的清除工作,而事实上,最规范的做法是我们应该对组件中使用的不必要异步操作进行清除。 例如:abort你的ajax请求或者清除定时器。

componentDidMount = () => {
    //ajax请求
    $.ajax('请求接口',{})
        .then(res => {
            this.setState({
                  pageState:true
            })
        })
        .catch(err => {})
    //setTimeout定时器
    timer = setTimeout(() => {
        //dosomething
    },1000)
}
componentWillUnMount = () => {
    //ajax请求
    $.ajax.abort()
    //setTimeout定时器
    clearTimeout(timer)
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

逸尘️

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

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

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

打赏作者

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

抵扣说明:

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

余额充值