Skip to content

Commit

Permalink
Add warning to prevent setting this.state to this.props referentially (
Browse files Browse the repository at this point in the history
…#11658)

* add test to warn if setting this.state to this.props referentially

* Avoid an extra check
  • Loading branch information
Veekas Shrivastava authored and gaearon committed Aug 28, 2018
1 parent 29287f0 commit 672e859
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 0 deletions.
21 changes: 21 additions & 0 deletions packages/react-dom/src/__tests__/ReactComponentLifeCycle-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,27 @@ describe('ReactComponentLifeCycle', () => {
}).not.toThrow();
});

it("warns if setting 'this.state = props'", () => {
class StatefulComponent extends React.Component {
constructor(props, context) {
super(props, context);
this.state = props;
}
render() {
return <div />;
}
}

expect(() => {
ReactTestUtils.renderIntoDocument(<StatefulComponent />);
}).toWarnDev(
'StatefulComponent: It is not recommended to assign props directly to state ' +
"because updates to props won't be reflected in state. " +
'In most cases, it is better to use props directly.',
{withoutStack: true},
);
});

it('should not allow update state inside of getInitialState', () => {
class StatefulComponent extends React.Component {
constructor(props, context) {
Expand Down
16 changes: 16 additions & 0 deletions packages/react-reconciler/src/ReactFiberClassComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,14 @@ let didWarnAboutLegacyLifecyclesAndDerivedState;
let didWarnAboutUndefinedDerivedState;
let warnOnUndefinedDerivedState;
let warnOnInvalidCallback;
let didWarnAboutDirectlyAssigningPropsToState;

if (__DEV__) {
didWarnAboutStateAssignmentForComponent = new Set();
didWarnAboutUninitializedState = new Set();
didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate = new Set();
didWarnAboutLegacyLifecyclesAndDerivedState = new Set();
didWarnAboutDirectlyAssigningPropsToState = new Set();
didWarnAboutUndefinedDerivedState = new Set();

const didWarnOnInvalidCallback = new Set();
Expand Down Expand Up @@ -674,6 +676,20 @@ function mountClassInstance(
instance.context = getMaskedContext(workInProgress, unmaskedContext);

if (__DEV__) {
if (instance.state === newProps) {
const componentName = getComponentName(ctor) || 'Component';
if (!didWarnAboutDirectlyAssigningPropsToState.has(componentName)) {
didWarnAboutDirectlyAssigningPropsToState.add(componentName);
warningWithoutStack(
false,
'%s: It is not recommended to assign props directly to state ' +
"because updates to props won't be reflected in state. " +
'In most cases, it is better to use props directly.',
componentName,
);
}
}

if (workInProgress.mode & StrictMode) {
ReactStrictModeWarnings.recordUnsafeLifecycleWarnings(
workInProgress,
Expand Down

0 comments on commit 672e859

Please sign in to comment.