220113实习学习碎片

react类组件异步更新,何时会同步,常报的错误

1、关于this.setState()

解决因为异步不能取到想要的值的:
1)this.setState()可接收一个函数作为参数
这个函数将接收两个参数,将前一个状态作为第一个参数,应用更新时的 props 作为第二个参数,如下:

this.setState((prevState, props) => ({
  number: prevState.number + props.increment
}));

2)执行setState()后能拿到最新的state值
setState()函数接收两个参数,一个是一个对象,表示更新当前的状态,一个是回调函数,是在设置状态成功之后调用,所以我们可以通过回调拿到最新的state值。代码如下:

updateNum = (arg) => {
    this.setState(
        { number: arg },
        () => {
            console.log(this.state.number);//输出最新number值
        }
    );
}

React会把this.state放到队列中,将它的更新设置成批处理,所以由 React 控制的事件处理过程 setState 不会同步更新 this.state!
也就是说,在 React 控制之外的情况, setState 会同步更新 this.state,绕过 React 通过 JavaScript 原生 addEventListener 直接添加的事件处理函数,还有使用 setTimeout/setInterval 等 React 无法掌控的 APIs情况下,就会出现同步更新 state 的情况。

咱就是举个🌰 来说:

class Finish extends PureComponent<Props> {
    state = {
        count: 1
    }
    componentDidMount() {
        document.querySelector('#btn-raw').addEventListener('click', this.onClick);
    }
//这里不是在Button组件里使用onClick,而是用JavaScript 原生 addEventListener 直接添加的事件处理函数
    onClick=()=> {
        this.setState({ count: this.state.count + 1 });
        console.log('# this.state', this.state);
    }
    render() {
        console.log('#enter render', this.state);
        return (
            <div>
                <div>{this.state.count}
                    <button id="btn-raw">Increment Raw</button>
                </div>
            </div>
        )
    }
}

export default Finish

这样在浏览器能实时的输出count,同步实现加一操作
在这里讲一下我犯的错误,初次写这段代码我是这样写的

onClick(){
        this.setState({ count: this.state.count + 1 });
        console.log('# this.state', this.state);
    }

导致报错:TypeError: Cannot read property ‘count’ of undefined

在这里插入图片描述
我想看看这个setState怎么回事,于是报了新的错误:
TypeError: this.setState is not a function
在这里插入图片描述
可是组件在第一次render的时候明明输出了count
在这里插入图片描述
经过排查才发现,是this指向出了问题,让我们来看看剪头函数和普通函数在react类组件中的指向:
在这里插入图片描述
在箭头函数中this指向当组件Finish;而在普通函数中this指向的是button按钮:
在这里插入图片描述
所以在触发点击事件之后它找不到this里面的state,因为根本没有
解决方法一:
最简单的就是用箭头函数
解决方法二:
bind绑定this

   constructor(props){
        super(props)
        this.state = {
            count: 1
        }
        this.onClick=this.onClick.bind(this)//此处不能偷懒直接写等号右边的,一定要写完整,否则绑定失败还是报错
    }
    componentDidMount() {
        document.querySelector('#btn-raw').addEventListener('click', this.onClick);
    }
    onClick(){
        console.log(this,'=====')
    }

2、在React中与state有关的报错

1)Can’t perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.

报错原因:
a、在网速慢的情况的,你去请求数据。然后看没有数据时,又返回出去了,等于你将组件卸载了,可过了一会数据回来之后,会报该错。
b、组件已经被销毁,而此时我们的异步操作(通常为调用接口更改state操作)还未结束。当我们的异步执行完成后要执行setState操作时,已经无法获得组件信息,由此造成该异常!
c、在组件挂载(mounted)之后进行了异步操作,比如ajax请求或者设置了定时器等,而你在callback中进行了setState操作。当你切换路由时,组件已经被卸载(unmounted)了,此时异步操作中callback还在执行,因此setState没有得到值。

解决方法:
法一:在卸载的时候对所有的操作进行清除(例如:abort你的ajax请求或者清除定时器)

componentWillUnMount = () => {
    //1.ajax请求
    $.ajax.abort()
    //2.定时器
    clearTimeout(timer)
}

法二:定个开关,组件卸载时候重置开关


componentDidMount = () => {
    this.flag = true;
    axios.get({'你的请求'})
        .then(res => {
            if(this.flag){
                this.setState({
                    aa:true
                })
            }
        })
        .catch(err => {})
}
componentWillUnMount = () => {
    this.flag = false;

法三:万金油

//以下三种写法都 🉑️
componentWillUnmount = () => {
    this.setState = (state,callback)=>{
      return;
    };
}
componentWillUnmount() {
    this.setState = ()=>false;//撤销setState
}
componentWillUnmount() {
    this.setState = ()=>{};//直接将setState重写
}

这是大佬做的关于setState同步异步的讲解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值