@samitouri / QOS-React / commits / 672e859d31

Add warning to prevent setting this.state to this.props referentially (#11658)

* add test to warn if setting this.state to this.props referentially * Avoid an extra check

Veekas Shrivastava committed Aug 28, 2018 at 09:17 UTC 672e859d311536ddf5f09fb47dcb84007703aa65
2 files changed +37
packages/react-dom/src/__tests__/ReactComponentLifeCycle-test.js
+21
@@ -198,6 +198,27 @@ describe('ReactComponentLifeCycle', () => {
198 }).not.toThrow();
199 });
200
201 + it("warns if setting 'this.state = props'", () => {
202 + class StatefulComponent extends React.Component {
203 + constructor(props, context) {
204 + super(props, context);
205 + this.state = props;
206 + }
207 + render() {
208 + return <div />;
209 + }
210 + }
211 +
212 + expect(() => {
213 + ReactTestUtils.renderIntoDocument(<StatefulComponent />);
214 + }).toWarnDev(
215 + 'StatefulComponent: It is not recommended to assign props directly to state ' +
216 + "because updates to props won't be reflected in state. " +
217 + 'In most cases, it is better to use props directly.',
218 + {withoutStack: true},
219 + );
220 + });
221 +
222 it('should not allow update state inside of getInitialState', () => {
223 class StatefulComponent extends React.Component {
224 constructor(props, context) {
packages/react-reconciler/src/ReactFiberClassComponent.js
+16
@@ -64,12 +64,14 @@ let didWarnAboutLegacyLifecyclesAndDerivedState;
64 let didWarnAboutUndefinedDerivedState;
65 let warnOnUndefinedDerivedState;
66 let warnOnInvalidCallback;
67 +let didWarnAboutDirectlyAssigningPropsToState;
68
69 if (__DEV__) {
70 didWarnAboutStateAssignmentForComponent = new Set();
71 didWarnAboutUninitializedState = new Set();
72 didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate = new Set();
73 didWarnAboutLegacyLifecyclesAndDerivedState = new Set();
74 + didWarnAboutDirectlyAssigningPropsToState = new Set();
75 didWarnAboutUndefinedDerivedState = new Set();
76
77 const didWarnOnInvalidCallback = new Set();
@@ -674,6 +676,20 @@ function mountClassInstance(
676 instance.context = getMaskedContext(workInProgress, unmaskedContext);
677
678 if (__DEV__) {
679 + if (instance.state === newProps) {
680 + const componentName = getComponentName(ctor) || 'Component';
681 + if (!didWarnAboutDirectlyAssigningPropsToState.has(componentName)) {
682 + didWarnAboutDirectlyAssigningPropsToState.add(componentName);
683 + warningWithoutStack(
684 + false,
685 + '%s: It is not recommended to assign props directly to state ' +
686 + "because updates to props won't be reflected in state. " +
687 + 'In most cases, it is better to use props directly.',
688 + componentName,
689 + );
690 + }
691 + }
692 +
693 if (workInProgress.mode & StrictMode) {
694 ReactStrictModeWarnings.recordUnsafeLifecycleWarnings(
695 workInProgress,