您当前的位置: 首页 > 

【03】

暂无认证

  • 2浏览

    0关注

    196博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

调研react的setState异步与同步

【03】 发布时间:2021-03-27 10:17:05 ,浏览量:2

关于setState

官网说明 https://zh-hans.reactjs.org/docs/faq-state.html#what-does-setstate-do

setstate在原生事件,setTimeout,setInterval,promise等异步操作中,state会同步更新

文档提到setState是异步的https://zh-hans.reactjs.org/docs/faq-state.html#when-is-setstate-asynchronous

那再了解一下setState是否能同步执行,答案是能

1、原生事件同步
import React, {Component} from 'react';
class Test4 extends Component {
    state = {
        n1: 0,
        n2: 0
    }
    onTab1(){
		this.setState({
            n1: this.state.n1 + 1
        })
        console.log("第一个n1",this.state.n1)
        this.setState({
            n1: this.state.n1 + 1
        })
        console.log("第二个n1",this.state.n1)
    }
    onTab2(){
        this.setState({
            n2: this.state.n2 + 1
        })
		console.log("第一个n2",this.state.n2)
        this.setState({
            n2: this.state.n2 + 1
        })
		console.log("第二个n2",this.state.n2)
    }
    componentDidMount() {
        document.getElementById("btn").addEventListener('click', this.onTab2.bind(this), false);
    }
    render() {
        return (
            
                n1:{this.state.n1}
                n2:{this.state.n2}
                合成事件测试同步
                原生事件测试同步
            
        );
    }
}

export default Test4;

onClick是react的合成事件,setState表现为异步。 addEventListener为原生事件,表现为同步

2、setTimeout同步
import React, {Component} from 'react';

class Test4 extends Component {
    state = {
        n1: 0,
        n2: 0
    }
    onTab1(){
        this.setState({
            n1: this.state.n1 + 1
        })
        console.log("第一个n1",this.state.n1)
        this.setState({
            n1: this.state.n1 + 1
        })
        console.log("第二个n1",this.state.n1)
    }
    onTab2(){
        setTimeout(()=>{
            this.setState({
                n2: this.state.n2 + 1
            })
            console.log("第二个n2",this.state.n2)
            this.setState({
                n2: this.state.n2 + 1
            })
            console.log("第二个n2",this.state.n2)
        },500)
    }

    render() {
        return (
            
                n1:{this.state.n1}
                n2:{this.state.n2}
                合成事件测试同步
                setTimeout测试同步
            
        );
    }
}

export default Test4;

3、promose同步
import React, {Component} from 'react';

class Test4 extends Component {
    state = {
        n1: 0,
        n2: 0
    }
    onTab1(){
        this.setState({
            n1: this.state.n1 + 1
        })
        console.log("第一个n1",this.state.n1)
        this.setState({
            n1: this.state.n1 + 1
        })
        console.log("第二个n1",this.state.n1)
    }
    onTab2(){
        new Promise(((resolve, reject) => {
            resolve()
        })).then(()=>{
            this.setState({
                n2: this.state.n2 + 1
            })
            console.log("第二个n2",this.state.n2)
            this.setState({
                n2: this.state.n2 + 1
            })
            console.log("第二个n2",this.state.n2)
        })
    }

    render() {
        return (
            
                n1:{this.state.n1}
                n2:{this.state.n2}
                合成事件测试同步
                Promise测试同步
            
        );
    }
}

export default Test4;

this.setState原理

setstate方法

ReactComponent.prototype.setState = function (partialState, callback) {
  //  将setState事务放进队列中
  this.updater.enqueueSetState(this, partialState);
  if (callback) {
    this.updater.enqueueCallback(this, callback, 'setState');
  }
};

enqueueSetState: function (publicInstance, partialState) {
     // 获取当前组件的instance
    var internalInstance = getInternalInstanceReadyForUpdate(publicInstance, 'setState');

     // 将要更新的state放入一个数组里
     var queue = internalInstance._pendingStateQueue || (internalInstance._pendingStateQueue = []);
    queue.push(partialState);

     //  将要更新的component instance也放在一个队列里
    enqueueUpdate(internalInstance);
  }
  
  function enqueueUpdate(component) {
 // 如果没有处于批量创建/更新组件的阶段,则处理update state事务
 if (!batchingStrategy.isBatchingUpdates) {
   batchingStrategy.batchedUpdates(enqueueUpdate, component);
   return;
 }
 // 如果正处于批量创建/更新组件的过程,将当前的组件放在dirtyComponents数组中
 dirtyComponents.push(component);
}

var ReactDefaultBatchingStrategy = {
  // 用于标记当前是否出于批量更新
  isBatchingUpdates: false,
  // 当调用这个方法时,正式开始批量更新
  batchedUpdates: function (callback, a, b, c, d, e) {
    var alreadyBatchingUpdates = ReactDefaultBatchingStrategy.isBatchingUpdates;

    ReactDefaultBatchingStrategy.isBatchingUpdates = true;

    // 如果当前事务正在更新过程在中,则调用callback,既enqueueUpdate
    if (alreadyBatchingUpdates) {
      return callback(a, b, c, d, e);
    } else {
    // 否则执行更新事务
      return transaction.perform(callback, null, a, b, c, d, e);
    }
  }
};


batchedUpdates 发起 transaction.perform() 事务 这个事务流程中的 anyMethod 是 runBatchedUpdates ,即更新组件状态并走一遍组件生命周期,在 componentWillMount 时将 A 状态队列里累积的状态都依次处理了。 wrapper close,循环遍历 dirtyComponents 并执行 transaction.perform(runBatchedUpdates, null, transaction); 于是 A 就被捡起来开始走事务流程直到 dirtyComponents 里最后一个组件跑完流程,组件都被统一更新了一遍。

以上源码内容分析来自https://www.jianshu.com/p/89a04c132270

再函数式组件中,都是异步
import React, {useState} from "react";
export default function Fn() {
    const [num1, setNum1] = useState(0);
    const [num2, setNum2] = useState(0);
    const onTab1 = () => {
        setNum1(num1 + 1)
        console.log("第一个num1", num1)
        setNum1(num1 + 1)
        console.log("第二个num1", num1)
    }

    const onTab2 = () => {
        setTimeout(()=>{
            setNum2(num2 + 1)
            console.log("第一个num2", num1)
            setNum2(num2 + 1)
            console.log("第二个num2", num1)
        },500)
    }
    return (
        
            num1:{num1}
            num2:{num2}
            默认异步
            setTimeout也是异步
        
    )
}

函数式组件state同步,执行顺序不同步写法
import React, {useState} from "react";
export default function Fn() {
    const [num1, setNum1] = useState(0);
    const [num2, setNum2] = useState(0);
    const onTab1 = () => {
        setNum1(num1 + 1)
        console.log("第一个num1", num1)
        setNum1(num1 + 1)
        console.log("第二个num1", num1)
    }

    const onTab2 = () => {
             setNum2(num2=>num2 + 1)
            console.log("第一个num2", num2)
             setNum2(num2 =>num2 + 1)
            console.log("第二个num2", num2)
    }
    return (
        
            num1:{num1}
            num2:{num2}
            默认异步
            state同步,执行顺序不同步
        
    )
}

注意:class组件和hooks都可以这样

关注
打赏
1657344724
查看更多评论
立即登录/注册

微信扫码登录

0.0400s