React源码剖析与完成(二):状况、属性更新 -> setState

原文链接地点:
https://github.com/Nealyang%EF%BC%9A%E7%8A%B6%E6%80%81%E3%80%81%E5%B1%9E%E6%80%A7%E6%9B%B4%E6%96%B0%20-%3E%20setState.md) 转载请说明出处

状况更新

此次剖析setState基于0.3版本,完成比较简朴,后续会再剖析如今运用的版本以及事件机制。

流程图也许以下

《React源码剖析与完成(二):状况、属性更新 -> setState》” /></span></p><p>setState的源码比较简朴,而在实行更新的历程比较复杂。我们直接随着源码一点一点屡清晰。</p><ul><li>ReactCompositeComponent.js</li></ul><pre><code>  /**
   * Sets a subset of the state. Always use this or `replaceState` to mutate
   * state. You should treat `this.state` as immutable.
   *
   * There is no guarantee that `this.state` will be immediately updated, so
   * accessing `this.state` after calling this method may return the old value.
   *
   * @param {object} partialState Next partial state to be merged with state.
   * @final
   * @protected
   */
  setState: function(partialState) {
    // Merge with `_pendingState` if it exists, otherwise with existing state.
    this.replaceState(merge(this._pendingState || this.state, partialState));
  },</code></pre><p>诠释部份说的很明白,setState后我们不能够马上拿到我们设置的值。</p><p>而这段代码也异常简朴,就是将我们传入的state和this._pendingState做一次merge,merge的代码在util.js下</p><pre><code>var merge = function(one, two) {
  var result = {};
  mergeInto(result, one);
  mergeInto(result, two);
  return result;
};

function mergeInto(one, two) {
  checkMergeObjectArg(one);
  if (two != null) {
    checkMergeObjectArg(two);
    for (var key in two) {
      if (!two.hasOwnProperty(key)) {
        continue;
      }
      one[key] = two[key];
    }
  }
}

  checkMergeObjectArgs: function(one, two) {
    mergeHelpers.checkMergeObjectArg(one);
    mergeHelpers.checkMergeObjectArg(two);
  },

  /**
   * @param {*} arg
   */
  checkMergeObjectArg: function(arg) {
    throwIf(isTerminal(arg) || Array.isArray(arg), ERRORS.MERGE_CORE_FAILURE);
  },
  
  var isTerminal = function(o) {
  return typeof o !== 'object' || o === null;
};

var throwIf = function(condition, err) {
  if (condition) {
    throw new Error(err);
  }
};</code></pre><p>诊断代码的逻辑异常简朴,实在功用就是<code>Object.assign()</code> ,然则从上面代码我们能够看出react源码中的function大多都具有小而巧的特性。</p><p>终究,将merge后的效果传递给<code>replaceState </code></p><pre><code>replaceState: function(completeState) {
    var compositeLifeCycleState = this._compositeLifeCycleState;
    invariant(
      this._lifeCycleState === ReactComponent.LifeCycle.MOUNTED ||
      compositeLifeCycleState === CompositeLifeCycle.MOUNTING,
      'replaceState(...): Can only update a mounted (or mounting) component.'
    );
    invariant(
      compositeLifeCycleState !== CompositeLifeCycle.RECEIVING_STATE &&
      compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING,
      'replaceState(...): Cannot update while unmounting component or during ' +
      'an existing state transition (such as within `render`).'
    );

    this._pendingState = completeState;

    // Do not trigger a state transition if we are in the middle of mounting or
    // receiving props because both of those will already be doing this.
    if (compositeLifeCycleState !== CompositeLifeCycle.MOUNTING &&
        compositeLifeCycleState !== CompositeLifeCycle.RECEIVING_PROPS) {
      this._compositeLifeCycleState = CompositeLifeCycle.RECEIVING_STATE;

      var nextState = this._pendingState;
      this._pendingState = null;

      var transaction = ReactComponent.ReactReconcileTransaction.getPooled();
      transaction.perform(
        this._receivePropsAndState,
        this,
        this.props,
        nextState,
        transaction
      );
      ReactComponent.ReactReconcileTransaction.release(transaction);

      this._compositeLifeCycleState = null;
    }
  },</code></pre><p>撇开50% 推断warning代码不说,从上面代码我们能够看出,只要在componsiteLifeState不等于mounting和receiving_props 时,才会挪用 _receivePropsAndState函数来更新组件。</p><p>我们能够演示下:</p><pre><code>var ExampleApplication = React.createClass({
      getInitialState() {
        return {}
      },
      componentWillMount() {
        this.setState({
          a: 1,
        })
        console.log('componentWillMount', this.state.a)
        this.setState({
          a: 2,
        })
        console.log('componentWillMount', this.state.a)
        this.setState({
          a: 3,
        })
        console.log('componentWillMount', this.state.a)
        setTimeout(() => console.log('a5'), 0)
        setTimeout(() => console.log(this.state.a,'componentWillMount'))

        Promise.resolve('a4').then(console.log)
      },

      componentDidMount() {
        this.setState({
          a: 4,
        })
        console.log('componentDidMount', this.state.a)
        this.setState({
          a: 5,
        })
        console.log('componentDidMount', this.state.a)
        this.setState({
          a: 6,
        })
        console.log('componentDidMount', this.state.a)
      },
      render: function () {
        var elapsed = Math.round(this.props.elapsed / 100);
        var seconds = elapsed / 10 + (elapsed % 10 ? '' : '.0');
        var message =
          'React has been successfully running for ' + seconds + ' seconds.';
        return React.DOM.p(null, message);
      }
    });</code></pre><p><span><img layer-src=     原文作者:isNealyang
    原文地址: https://segmentfault.com/a/1190000016174825
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。

点赞