• react——setState源码解析


    源码在node_modules/react/.目录下

     1、node_modules/react/dist/react.js

    定义了ReactComponent

    function ReactComponent(props, context, updater) {
      this.props = props;
      this.context = context;
      this.refs = emptyObject;
      // We initialize the default updater but the real one gets injected by the
      // renderer.
      this.updater = updater || ReactNoopUpdateQueue;
    }

    定义了ReactComponent的prototype

    ReactComponent.prototype.isReactComponent = {};
    
    ReactComponent.prototype.setState = function (partialState, callback) {
      !(typeof partialState === 'object' || typeof partialState === 'function' || partialState == null) ? "development" !== 'production' ? invariant(false, 'setState(...): takes an object of state variables to update or a ' + 'function which returns an object of state variables.') : invariant(false) : undefined;
      if ("development" !== 'production') {
        "development" !== 'production' ? warning(partialState != null, 'setState(...): You passed an undefined or null state object; ' + 'instead, use forceUpdate().') : undefined;
      }
      this.updater.enqueueSetState(this, partialState);
      if (callback) {
        this.updater.enqueueCallback(this, callback);
      }
    };
    
    ReactComponent.prototype.forceUpdate = function (callback) {
      this.updater.enqueueForceUpdate(this);
      if (callback) {
        this.updater.enqueueCallback(this, callback);
      }
    };

    updater的两处定义在node_modules/react/lib/ReactUpdateQueue.js和node_modules/react/lib/ReactNoopUpdateQueue.js

    2、node_modules/react/lib/ReactNoopUpdateQueue.js

    定义了ReactNoopUpdateQueue的空操作Noop:

      1 /**
      2  * Copyright 2015, Facebook, Inc.
      3  * All rights reserved.
      4  *
      5  * This source code is licensed under the BSD-style license found in the
      6  * LICENSE file in the root directory of this source tree. An additional grant
      7  * of patent rights can be found in the PATENTS file in the same directory.
      8  *
      9  * @providesModule ReactNoopUpdateQueue
     10  */
     11 
     12 'use strict';
     13 
     14 var warning = require('fbjs/lib/warning');
     15 
     16 function warnTDZ(publicInstance, callerName) {
     17   if (process.env.NODE_ENV !== 'production') {
     18     process.env.NODE_ENV !== 'production' ? warning(false, '%s(...): Can only update a mounted or mounting component. ' + 'This usually means you called %s() on an unmounted component. ' + 'This is a no-op. Please check the code for the %s component.', callerName, callerName, publicInstance.constructor && publicInstance.constructor.displayName || '') : undefined;
     19   }
     20 }
     21 
     22 /**
     23  * This is the abstract API for an update queue.
     24  */
     25 var ReactNoopUpdateQueue = {
     26 
     27   /**
     28    * Checks whether or not this composite component is mounted.
     29    * @param {ReactClass} publicInstance The instance we want to test.
     30    * @return {boolean} True if mounted, false otherwise.
     31    * @protected
     32    * @final
     33    */
     34   isMounted: function (publicInstance) {
     35     return false;
     36   },
     37 
     38   /**
     39    * Enqueue a callback that will be executed after all the pending updates
     40    * have processed.
     41    *
     42    * @param {ReactClass} publicInstance The instance to use as `this` context.
     43    * @param {?function} callback Called after state is updated.
     44    * @internal
     45    */
     46   enqueueCallback: function (publicInstance, callback) {},
     47 
     48   /**
     49    * Forces an update. This should only be invoked when it is known with
     50    * certainty that we are **not** in a DOM transaction.
     51    *
     52    * You may want to call this when you know that some deeper aspect of the
     53    * component's state has changed but `setState` was not called.
     54    *
     55    * This will not invoke `shouldComponentUpdate`, but it will invoke
     56    * `componentWillUpdate` and `componentDidUpdate`.
     57    *
     58    * @param {ReactClass} publicInstance The instance that should rerender.
     59    * @internal
     60    */
     61   enqueueForceUpdate: function (publicInstance) {
     62     warnTDZ(publicInstance, 'forceUpdate');
     63   },
     64 
     65   /**
     66    * Replaces all of the state. Always use this or `setState` to mutate state.
     67    * You should treat `this.state` as immutable.
     68    *
     69    * There is no guarantee that `this.state` will be immediately updated, so
     70    * accessing `this.state` after calling this method may return the old value.
     71    *
     72    * @param {ReactClass} publicInstance The instance that should rerender.
     73    * @param {object} completeState Next state.
     74    * @internal
     75    */
     76   enqueueReplaceState: function (publicInstance, completeState) {
     77     warnTDZ(publicInstance, 'replaceState');
     78   },
     79 
     80   /**
     81    * Sets a subset of the state. This only exists because _pendingState is
     82    * internal. This provides a merging strategy that is not available to deep
     83    * properties which is confusing. TODO: Expose pendingState or don't use it
     84    * during the merge.
     85    *
     86    * @param {ReactClass} publicInstance The instance that should rerender.
     87    * @param {object} partialState Next partial state to be merged with state.
     88    * @internal
     89    */
     90   enqueueSetState: function (publicInstance, partialState) {
     91     warnTDZ(publicInstance, 'setState');
     92   },
     93 
     94   /**
     95    * Sets a subset of the props.
     96    *
     97    * @param {ReactClass} publicInstance The instance that should rerender.
     98    * @param {object} partialProps Subset of the next props.
     99    * @internal
    100    */
    101   enqueueSetProps: function (publicInstance, partialProps) {
    102     warnTDZ(publicInstance, 'setProps');
    103   },
    104 
    105   /**
    106    * Replaces all of the props.
    107    *
    108    * @param {ReactClass} publicInstance The instance that should rerender.
    109    * @param {object} props New props.
    110    * @internal
    111    */
    112   enqueueReplaceProps: function (publicInstance, props) {
    113     warnTDZ(publicInstance, 'replaceProps');
    114   }
    115 
    116 };
    117 
    118 module.exports = ReactNoopUpdateQueue;
    View Code

    主要看ReactUpdateQueue.js

    3、node_modules/react/lib/ReactUpdateQueue.js

    这儿主要分析enqueueCallback和enqueueSetState。

    var ReactUpdateQueue = {
    
      /**
       * Enqueue a callback that will be executed after all the pending updates
       * have processed.
       *
       * @param {ReactClass} publicInstance The instance to use as `this` context.
       * @param {?function} callback Called after state is updated.
       * @internal
       */
      enqueueCallback: function (publicInstance, callback) {
        !(typeof callback === 'function') ? process.env.NODE_ENV !== 'production' ? invariant(false, 'enqueueCallback(...): You called `setProps`, `replaceProps`, ' + '`setState`, `replaceState`, or `forceUpdate` with a callback that ' + 'isn\'t callable.') : invariant(false) : undefined;
        var internalInstance = getInternalInstanceReadyForUpdate(publicInstance);
    
        // Previously we would throw an error if we didn't have an internal
        // instance. Since we want to make it a no-op instead, we mirror the same
        // behavior we have in other enqueue* methods.
        // We also need to ignore callbacks in componentWillMount. See
        // enqueueUpdates.
        if (!internalInstance) {
          return null;
        }
    
        if (internalInstance._pendingCallbacks) {
          internalInstance._pendingCallbacks.push(callback);
        } else {
          internalInstance._pendingCallbacks = [callback];
        }
        // TODO: The callback here is ignored when setState is called from
        // componentWillMount. Either fix it or disallow doing so completely in
        // favor of getInitialState. Alternatively, we can disallow
        // componentWillMount during server-side rendering.
        enqueueUpdate(internalInstance);
      },
    }
  • 相关阅读:
    H5调用本地摄像头
    zepto和jquery的区别,zepto的不同使用8条小结
    web前端页面性能优化小结
    超赞!聊聊WEB APP、HYBRID APP与NATIVE APP的设计差异
    activemq生产者和消费者的双向通信
    消息队列同步和异步机制
    postman使用教程
    spring boot mybatis sql打印到控制台
    spring boot 整合 mybatis 以及原理
    spring 框架整合mybatis的源码分析
  • 原文地址:https://www.cnblogs.com/sunupo/p/15899492.html
Copyright © 2020-2023  润新知