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
/** * 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
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 = newComponentDummy()); 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 = newComponentDummy()); 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; };