React 之 setState

前言:

    state是React中非常重要的概念。React通过管理状态来实现对组件的管理,React通过this.state来访问state,又通过this.setState()来更新state,当this.setState()方法被调用时,React会重新调用render函数来重新渲染UI。

一、setState异步更新

    setState通过一个队列机制实现state更新。当执行setState时,会将需要更新的state合并后放入状态队列,而不会立刻更新this.state,队列机制可以高效批量更新state。如果不通过setState而直接修改this.state的值,那么该state将不会被放入状态队列中,当下次调用setState并对队列进行合并时,将会忽略之前直接被修改(例:this.state.value=1)的state,而造成无法预知的错误。

 相关代码如下:

  

//将新的state合并到状态更新队列中
var nextState =  this._processPendingState(nextProps,nextContext);

//根据更新队列和 shouldComponentUpdate 的状态来判断是否需要更新组件
var shouldUpdate = 
    this._pendingForceUpdate ||
    !inst.shouldComponentUpdate ||
    inst.shouldComponentUpdate(nextProps,nextState,nextContext);

setState()方法是一个异步函数,可以传入回调函数。this.setState({...state},callback);

 

二、setState循环调用风险

  当调用setStae()方式时,实际上会执行enqueueSetState方法,并对partialState以及_pendingStateQueue更新队列进行合并操作,最终通过enqueueUpdate执行state更新。

而performUpdateIfNecessary方法会获取_pendingElement、_pendingStateQueue、_pendingForceUpdate,并调用revceviceComponent和updtaComponent方法进行组件更新。

如果在 shouldComponentUpdate或compponentWillUpdate方法中调用setState,此时this._pendingStateQueue!=null,则performUpdateIfNecessary方法就会调用updataComponent方法进行组件更新,但updateComponent方法又会调用shouldComponentUpdate和componentWillUpdate方法,因此造成循环调用,使得浏览器内存沾满后崩溃。

三、setState调用栈

      enqueueUpdate 的作用是判断 batchingStrategy.isBatchingUpdates 如果是 true,则对所有队列中的更新执行 batchUpdates 方法,否则只把当前组件(调用了 setState 的组件)放入 dirtyComponents 数组中。

 

enqueueupdate源码:

function enqueueUpdate(component){
  ensureInjected();
  // 如果不是批量更新模式
  if (!batchingStrategy.isBatchingUpdates){
    batchingStrategy.batchingUpdates(enqueueUpdate, component);
    return ;
  }
  // 如果处于批量更新模式 则将该组件保存在 dirtyComponents 中
  dirtyComponents.push(component)
}

batchingStrategy 只是定义了一个 Boolean 类型的变量 isBatchingUpdates 和 一个 batchedUpdates 方法:

var ReactDefaultBatchingStrategy = {
    isBatchingUpdates: false,
    batchedUpdates: function(callback, a, b, c, d, e) {
        var alreadyBatchingUpdates = ReactDefaultBatchingStrategy.isBatchingUpdates;
        ReactDefaultBatchingStrategy.isBatchingUpdates = true;
        if (alreadyBatchingUpdates) {
            callback(a, b, c, d, e);
        } else {
            // transaction.perform 涉及一个事务的概念
            transaction.perform(callback, null, a, b, c, d, e);
        }
    },
}

四、 事务

   

这里事务的概念如下:

将需要执行的方法使用 wrapper 封装起来,再通过事务提供的 perform 方法执行。

在 perform 之前,先执行所有 wrapper 中的 initialize 方法,执行完 perform 方法之后(执行 method 方法后)再执行所有的 close 方法。

一组 initialize 及 close 方法称为一个 wrapper,多个 wrapper 可以叠加。

如下图所示:

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值