Warn about setState inside getChildContext

Stack uses a module called ReactInvalidSetStateWarningHook, but all it
does is warn about setState inside getChildContext. Doesn't seem worth
keeping around, so I didn't use it for Fiber, but if I'm mistaken I'll
change it.
This commit is contained in:
Andrew Clark
2017-02-24 11:02:21 -08:00
parent 5f7fc576bc
commit e646f5a79f
4 changed files with 46 additions and 10 deletions
@@ -106,7 +106,6 @@ src/renderers/__tests__/ReactComponentTreeHook-test.native.js
* does not report top-level wrapper as a root
src/renderers/__tests__/ReactCompositeComponent-test.js
* should warn about `setState` in getChildContext
* should disallow nested render calls
src/renderers/__tests__/ReactHostOperationHistoryHook-test.js
+1
View File
@@ -578,6 +578,7 @@ src/renderers/__tests__/ReactCompositeComponent-test.js
* should warn about `setState` on unmounted components
* should silently allow `setState`, not call cb on unmounting components
* should warn about `setState` in render
* should warn about `setState` in getChildContext
* should cleanup even if render() fatals
* should call componentWillUnmount before unmounting
* should warn when shouldComponentUpdate() returns undefined
@@ -47,6 +47,21 @@ let didPerformWorkStackCursor : StackCursor<boolean> = createCursor(false);
// pushed the next context provider, and now need to merge their contexts.
let previousContext : Object = emptyObject;
if (__DEV__) {
var _isProcessingChildContext = false;
var onBeginProcessingChildContext = function() {
_isProcessingChildContext = true;
};
exports.onBeginProcessingChildContext = onBeginProcessingChildContext;
var onEndProcessingChildContext = function() {
_isProcessingChildContext = false;
};
exports.onEndProcessingChildContext = onEndProcessingChildContext;
exports.isProcessingChildContext = function() : boolean {
return _isProcessingChildContext;
};
}
function getUnmaskedContext(workInProgress : Fiber) : Object {
const hasOwnContext = isContextProvider(workInProgress);
if (hasOwnContext) {
@@ -144,6 +159,10 @@ exports.pushTopLevelContextObject = function(fiber : Fiber, context : Object, di
};
function processChildContext(fiber : Fiber, parentContext : Object, isReconciling : boolean): Object {
if (__DEV__) {
onBeginProcessingChildContext();
}
const instance = fiber.stateNode;
const childContextTypes = fiber.type.childContextTypes;
@@ -189,6 +208,11 @@ function processChildContext(fiber : Fiber, parentContext : Object, isReconcilin
checkReactTypeSpec(childContextTypes, childContext, 'child context', name);
ReactDebugCurrentFrame.current = null;
}
if (__DEV__) {
onEndProcessingChildContext();
}
return {...parentContext, ...childContext};
}
exports.processChildContext = processChildContext;
@@ -90,6 +90,10 @@ if (__DEV__) {
var warning = require('warning');
var ReactFiberInstrumentation = require('ReactFiberInstrumentation');
var ReactDebugCurrentFiber = require('ReactDebugCurrentFiber');
var {
isProcessingChildContext,
onEndProcessingChildContext,
} = require('ReactFiberContext');
var warnAboutUpdateOnUnmounted = function(instance : ReactClass<any>) {
const ctor = instance.constructor;
@@ -103,14 +107,21 @@ if (__DEV__) {
);
};
var warnAboutUpdateInRender = function(instance : ReactClass<any>) {
warning(
ReactCurrentOwner.current == null,
'Cannot update during an existing state transition (such as within ' +
'`render` or another component\'s constructor). Render methods should ' +
'be a pure function of props and state; constructor side-effects are ' +
'an anti-pattern, but can be moved to `componentWillMount`.'
);
var warnAboutInvalidUpdates = function(instance : ReactClass<any>) {
if (isProcessingChildContext()) {
warning(
false,
'setState(...): Cannot call setState() inside getChildContext()',
);
} else if (ReactCurrentOwner.current != null) {
warning(
false,
'Cannot update during an existing state transition (such as within ' +
'`render` or another component\'s constructor). Render methods should ' +
'be a pure function of props and state; constructor side-effects are ' +
'an anti-pattern, but can be moved to `componentWillMount`.'
);
}
};
}
@@ -869,6 +880,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
ReactCurrentOwner.current = null;
if (__DEV__) {
ReactDebugCurrentFiber.current = null;
onEndProcessingChildContext();
}
// It is no longer valid because this unit of work failed.
nextUnitOfWork = null;
@@ -1115,7 +1127,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
if (__DEV__) {
if (fiber.tag === ClassComponent) {
const instance = fiber.stateNode;
warnAboutUpdateInRender(instance);
warnAboutInvalidUpdates(instance);
}
}