拆解setState[一][一源看世界][之React]

作者: 蛋先生DX | 来源:发表于2016-07-08 11:34 被阅读1464次

有惊无险地看完了setState源码的精彩内容,正打算整理一下激动的情绪,梳理一下逻辑,记下读后感,然后就在React功夫网发现了同样介绍setState的文章,感觉作者的思路很清晰,所以就打算在参考它的基础上把这篇文章给撸完。
go go go ...

首先得先找到入口,在ReactClass.createClass声明构造函数的代码中Constructor.prototype = new ReactClassComponent();,可以看出构造函数的原型继承自ReactClassComponent,而ReactClassComponent的源码如下:

var ReactClassComponent = function() {};
Object.assign(
  ReactClassComponent.prototype,
  ReactComponent.prototype,
  ReactClassMixin
);

ReactClassComponent的原型又合并了ReactComponent的原型,所以构造函数Constructor的原型也就有了ReactComponent.prototypesetState的方法。
SO,我们看一下ReactComponent.prototype.setState的方法实现吧。

首先看下这个方法的注释

Sets a subset of the state. Always use this 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.

There is no guarantee that calls to setState will run synchronously,
as they may eventually be batched together. You can provide an optional
callback that will be executed when the call to setState is actually
completed.

When a function is provided to setState, it will be called at some point in the future (not synchronously). It will be called with the up to date component arguments (state, props, context). These values can be different from this.because your function may be called after receiveProps but before shouldComponentUpdate, and this new state, props, and context will not yet be assigned to this.

提取一下上面的大概中心思想:

  1. 通过setState去更新this.state不要直接操作this.state,请把它当成不可变的。
  2. 调用setState更新this.state不是马上生效的,它是异步滴,所以不要天真以为执行完setStatethis.state就是最新的值了。
  3. 多个顺序执行的setState不是同步地一个一个执行滴,会一个一个加入队列,然后最后一起执行,即批处理

那,有了个大概认识,就开始深入探险吧,Let's go...

ReactComponent.prototype.setState = function(partialState, callback) {
  ...
  this.updater.enqueueSetState(this, partialState);
  if (callback) {
    this.updater.enqueueCallback(this, callback, 'setState');
  }
};
  • setState被加入updater的队列来执行它的工作。
  • callback也被加入updater的队列,如果存在的话。

别急,接下来你会明白为什么的。

updater是什么呢?这个名称意味着它会与更新组件有关。先来看看它在哪里定义吧。在ReactClass.createClassReactComponent的构造函数中,可以看到

this.updater = updater || ReactNoopUpdateQueue;

React的源码中大量应用依赖注入原理,这使得React.js可以优雅地实现在不同平台下(服务器端,浏览器端,手机端等)的渲染。ReactComponent脚本存在于isomorphic目录 - 意味着它支持异构,即它可用于React Native,在浏览器端或服务器端运行的ReactDOM

那,真实的updater在哪里被注入的呢?那就得知道ReactComponent Class在哪里被New,经过千山万水,终于在ReactCompositeComponent_constructComponentWithoutOwner方法中找到

  _constructComponentWithoutOwner: function(publicProps, publicContext) {
    var Component = this._currentElement.type;
    var instanceOrElement;
    if (shouldConstruct(Component)) {
      ...
      instanceOrElement = new Component(publicProps, publicContext, ReactUpdateQueue);
      ...
    } else {
      ...
    }
    return instanceOrElement;
  },

可以看出updaterReactUpdateQueue,这就真的找到了吗?其实不然,我们顺着往上找,经过_constructComponent,最终定位到mountComponent,从这句代码inst.updater = ReactUpdateQueue;可以看出最终的updater,还是ReactUpdateQueue,哈哈,虽然没变,但最终决定updater的值确实就是这里。

OK,知道了这个updater的真面目,那~,我们先休息一下吧,在下章节我们再来深入了解enqueueSetStateenqueueCallback是怎么工作的吧。


最后,期待吐槽,期待指教!!!

--EOF--

相关文章

网友评论

    本文标题:拆解setState[一][一源看世界][之React]

    本文链接:https://www.haomeiwen.com/subject/ixuljttx.html