mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Improve warning message for setState-on-unmounted (#12347)
This is one of the most common warnings people see, and I don't think the old text is especially clear. Improve it.
This commit is contained in:
committed by
Dan Abramov
parent
7a833dad95
commit
5855e9f215
@@ -244,10 +244,11 @@ describe('ReactCompositeComponent', () => {
|
||||
ReactDOM.unmountComponentAtNode(container);
|
||||
|
||||
expect(() => instance.forceUpdate()).toWarnDev(
|
||||
'Can only update a mounted or mounting component. This usually means ' +
|
||||
'you called setState, replaceState, or forceUpdate on an unmounted ' +
|
||||
'component. This is a no-op.\n\nPlease check the code for the ' +
|
||||
'Component component.',
|
||||
"Warning: Can't call setState (or forceUpdate) on an unmounted " +
|
||||
'component. This is a no-op, but it indicates a memory leak in your ' +
|
||||
'application. To fix, cancel all subscriptions and asynchronous ' +
|
||||
'tasks in the componentWillUnmount method.\n' +
|
||||
' in Component (at **)',
|
||||
);
|
||||
|
||||
// No additional warning should be recorded
|
||||
@@ -269,10 +270,15 @@ describe('ReactCompositeComponent', () => {
|
||||
}
|
||||
}
|
||||
|
||||
let instance = <Component />;
|
||||
expect(instance.setState).not.toBeDefined();
|
||||
|
||||
instance = ReactDOM.render(instance, container);
|
||||
let instance;
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<span>
|
||||
<Component ref={c => (instance = c || instance)} />
|
||||
</span>
|
||||
</div>,
|
||||
container,
|
||||
);
|
||||
|
||||
expect(renders).toBe(1);
|
||||
|
||||
@@ -280,15 +286,17 @@ describe('ReactCompositeComponent', () => {
|
||||
|
||||
expect(renders).toBe(2);
|
||||
|
||||
ReactDOM.unmountComponentAtNode(container);
|
||||
ReactDOM.render(<div />, container);
|
||||
|
||||
expect(() => {
|
||||
instance.setState({value: 2});
|
||||
}).toWarnDev(
|
||||
'Can only update a mounted or mounting component. This usually means ' +
|
||||
'you called setState, replaceState, or forceUpdate on an unmounted ' +
|
||||
'component. This is a no-op.\n\nPlease check the code for the ' +
|
||||
'Component component.',
|
||||
"Warning: Can't call setState (or forceUpdate) on an unmounted " +
|
||||
'component. This is a no-op, but it indicates a memory leak in your ' +
|
||||
'application. To fix, cancel all subscriptions and asynchronous ' +
|
||||
'tasks in the componentWillUnmount method.\n' +
|
||||
' in Component (at **)\n' +
|
||||
' in span',
|
||||
);
|
||||
|
||||
expect(renders).toBe(2);
|
||||
|
||||
+8
-5
@@ -14,6 +14,7 @@ import type {HydrationContext} from './ReactFiberHydrationContext';
|
||||
import type {ExpirationTime} from './ReactFiberExpirationTime';
|
||||
|
||||
import ReactErrorUtils from 'shared/ReactErrorUtils';
|
||||
import {getStackAddendumByWorkInProgressFiber} from 'shared/ReactFiberComponentTreeHook';
|
||||
import {ReactCurrentOwner} from 'shared/ReactGlobalSharedState';
|
||||
import ReactStrictModeWarnings from './ReactStrictModeWarnings';
|
||||
import {
|
||||
@@ -112,17 +113,19 @@ if (__DEV__) {
|
||||
const didWarnStateUpdateForUnmountedComponent = {};
|
||||
|
||||
warnAboutUpdateOnUnmounted = function(fiber: Fiber) {
|
||||
// We show the whole stack but dedupe on the top component's name because
|
||||
// the problematic code almost always lies inside that component.
|
||||
const componentName = getComponentName(fiber) || 'ReactClass';
|
||||
if (didWarnStateUpdateForUnmountedComponent[componentName]) {
|
||||
return;
|
||||
}
|
||||
warning(
|
||||
false,
|
||||
'Can only update a mounted or mounting ' +
|
||||
'component. This usually means you called setState, replaceState, ' +
|
||||
'or forceUpdate on an unmounted component. This is a no-op.\n\nPlease ' +
|
||||
'check the code for the %s component.',
|
||||
componentName,
|
||||
"Can't call setState (or forceUpdate) on an unmounted component. This " +
|
||||
'is a no-op, but it indicates a memory leak in your application. To ' +
|
||||
'fix, cancel all subscriptions and asynchronous tasks in the ' +
|
||||
'componentWillUnmount method.%s',
|
||||
getStackAddendumByWorkInProgressFiber(fiber),
|
||||
);
|
||||
didWarnStateUpdateForUnmountedComponent[componentName] = true;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user