Dogtiti / Blogs

:sparkling_heart:一起记笔记呀~
8 stars 6 forks source link

setState是同步还是异步的 #39

Open yinyinnnn opened 3 years ago

yixiaosi1314 commented 3 years ago

setState是同步还是异步的?

setState方法是同步的,但是通过setState处理state数据可能是同步也可能是异步的。

由于react的性能优化机制会让setState体现为异步形式

我们看看下面代码
state = {
   num: 0
}
componentDidMount() {
    this.setState({ num: this.state.num + 1 })
    console.log(this.state.num);//0
}

render() {
    const { num } = this.state
    return (
        <div className='box'>
            {num} //1
        </div>
    )
}
state = {
   num: 0
}
add = () => {
    this.setState({ num: this.state.num + 1 })
    console.log(this.state.num);//0
}
render() {
    const { num } = this.state
    return (
        <div className='box'>
            {num} //1
            <button onClick={this.addNum}>加1</button>
        </div>
    )
}

第一段代码中我们可以看到在生命周期函数中处理数据打印的结果为0,但是页面显示的内容为1。

第二段代码中通过react的onclick事件函数中,点击一次按钮后,同样打印的结果为0,但是页面显示的内容为1。

由此我们可以知道setState在这些情况下是同步的,但是处理数据是异步的。打印数据的时候state数据还没有更新。

如果我们需要及时拿到数据的话,可以通过回调函数的方法拿到更新后的数据

state = {
    num: 0
}
componentDidMount() {
    this.setState({ num: this.state.num + 1 },() => {
        console.log(this.state.num);//1
    })
}

此时打印数据会在state数据更新,页面重新渲染之后,在执行setState中的回调函数,所以此时打印的数据是1。

我们如果能越过react机制呢?

state = {
    num: 1
}
componentDidMount() {
    setTimeout(() => {
        this.setState({ num: this.state.num + 1 })
        console.log('settime', this.state.num);//2
        this.setState({ num: this.state.num + 1 })
        console.log('settime', this.state.num);//3
    }, 0);
}

由上面代码可以看到,越过react,在原生js比如setTimeout环境下,我们可以通过结果看到,此时的setState表现为同步的形式。

总结

setState是同步的,只是因为在react性能优化的机制下,在react生命周期函数或者作用域下才会以异步的形式体现,在原生js环境下都是同步。