基于React 源码深入浅出setState:setState异步实现

作者 : 墨成

React 版本 :16.4.1

React启示录里我们说setState是异步的,我们在代码中也展示了这种特性,那么FB的工程师们是如何实现呢,本文将基于React的源码进一步揭开这层面纱。

在介绍之前我们首先看下setState的实现和FB工程师的注释,我简单的作了一些翻译

//ReactBaseClass.js
/**
 * Sets a subset of the state. Always use this to mutate
 * state. You should treat `this.state` as immutable.
 * //我们应该使用这个方法(setState)来改变state,而不是使用this.state(翻译可能跟原文有一点偏差,当表达的意思是这样)
 * There is no guarantee that `this.state` will be immediately updated, so
 * accessing `this.state` after calling this method may return the old value.
 *//setState并不会立即更新,在调用这个方法后拿到的this.state可能还是原来的值
 * 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.
 *//setState不能保证是同步的,他们有可能会批量处理。你可以提供一个可选的回调函数来拿到更改之后的值
 * 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.
 *//setState第一参数是一个function ,他会在未来的某个时间点执行。在执行这个functon时我们都是拿到的最新的组件信息
 *//(比如state,props, context).这些值根尼通过this.state的不一样,因为function实在receiveProps之后在
 *//shouldComponentDupdate之前,所以这些值还没更新到当前this指向的这些值 
 * @param {object|function} partialState Next partial state or function to
 *        produce next partial state to be merged with current state.
 * @param {?function} callback Called after state is updated.
 * @final
 * @protected
 */
Component.prototype.setState = function(partialState, callback) {
  invariant(
    typeof partialState === 'object' ||
      typeof partialState === 'function' ||
      partialState == null,
    'setState(...): takes an object of state variables to update or a ' +
      'function which returns an object of state variables.',
  );
  this.updater.enqueueSetState(this, partialState, callback, 'setState');
};复制代码

 上面的注释告诉我们:

1.setState()第一参数是function也是异步的

2.function的执行周期是:receiveProps=>function=>shouldComponentUpdate

3. 基于第二点的说明,再回头看看官网对function的写法,我们知道为什么这个函数的第一参数叫 preState ,而props 就叫props而不是叫preProps的原因了.

(prevState, props) => stateChange复制代码

如果关于第一参数function的说明还不是很理解,多看几眼,多想想React生命周期,那就会茅塞顿开 .

言归正传,再看看整段代码

Component.prototype.setState = function(partialState, callback) {
  invariant(
    typeof partialState === 'object' ||
      typeof partialState === 'function' ||
      partialState == null,
    'setState(...): takes an object of state variables to update or a ' +
      'function which returns an object of state variables.',
  );
  this.updater.enqueueSetState(this, partialState, callback, 'setState');
};复制代码

参数:

@param  partialState 部分状态复制代码

这个参数或许是整个state,或许只是state其中的一部分 ,最终React合并(就是merge).

state = {name:'myName',age:18} => setState({age:16}/*state的一部分*/)=>state={name:'myName',age:16}复制代码

其实就是Object.assign的理解 .

@param  callback 回调函数,后面专门开一篇来讲解
复制代码



invariant 没什么好解释的 ,代码位于shared/invariant,是对error的一种封装,有兴趣的同学可以看看复制代码

今天就到这里,未完待续.......


猜你喜欢

转载自juejin.im/post/5b488d0b5188251b3950ceb8