var ReactNoopUpdateQueue = require('ReactNoopUpdateQueue');
var emptyObject = require('fbjs/lib/emptyObject'); var invariant = require('fbjs/lib/invariant'); var lowPriorityWarning = require('lowPriorityWarning');
/** * Base class helpers for the updating state of a component. */ functionReactComponent(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.isReactComponent = {};
ReactComponent.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'); };
给它添加 setState 方法,实际操作就是把下一个要设置的 state 放入到更新队列里面。注释中提到:
永远使用 setState 这个方法去更改 state ,你应该认为 this.state 是不可变的
不保证 this.state 会及时更新,也就是说调用 this.state 可能拿到的还是旧的 state
一个强制更新的方法,这个方法不会触发 shoudleComponentUpdate ,但是会正常调用 componentWillUpdate 和 componentDidUpdate . 要确保调用这个方法的时候,所有的 DOM 事务操作已经完成。 只有在当你知道一个组件的深层次的 state 变化了,但是并没有调用 setState 的时候才需要调用这个方法。
不推荐的方法
/** * Deprecated APIs. These APIs used to exist on classic React classes but since * we would like to deprecate them, we're not going to move them over to this * modern base class. Instead, we define a getter that warns if it's accessed. */ if (__DEV__) { var deprecatedAPIs = { isMounted: [ 'isMounted', 'Instead, make sure to clean up subscriptions and pending requests in ' + 'componentWillUnmount to prevent memory leaks.', ], replaceState: [ 'replaceState', 'Refactor your code to use setState instead (see ' + 'https://github.com/facebook/react/issues/3236).', ], }; var defineDeprecationWarning = function(methodName, info) { Object.defineProperty(ReactComponent.prototype, methodName, { get: function() { lowPriorityWarning( false, '%s(...) is deprecated in plain JavaScript React classes. %s', info[0], info[1], ); returnundefined; }, }); }; for (var fnName in deprecatedAPIs) { if (deprecatedAPIs.hasOwnProperty(fnName)) { defineDeprecationWarning(fnName, deprecatedAPIs[fnName]); } } }
这里可以看到 isMounted 和 replaceState 这两个方法,已经被官方认为将要废弃的 API ,在开发过程中应该尽量避免使用它们。
PureComponent
functionReactPureComponent(props, context, updater) { // Duplicated from ReactComponent. 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; }
functionComponentDummy() {} ComponentDummy.prototype = ReactComponent.prototype; var pureComponentPrototype = (ReactPureComponent.prototype = new ComponentDummy()); pureComponentPrototype.constructor = ReactPureComponent; // Avoid an extra prototype jump for these methods. Object.assign(pureComponentPrototype, ReactComponent.prototype); pureComponentPrototype.isPureReactComponent = true;
functionReactAsyncComponent(props, context, updater) { // Duplicated from ReactComponent. 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; }
var asyncComponentPrototype = (ReactAsyncComponent.prototype = new ComponentDummy()); asyncComponentPrototype.constructor = ReactAsyncComponent; // Avoid an extra prototype jump for these methods. Object.assign(asyncComponentPrototype, ReactComponent.prototype); asyncComponentPrototype.unstable_isAsyncReactComponent = true; asyncComponentPrototype.render = function() { returnthis.props.children; };