diff --git a/packages/react-dom/src/__tests__/ReactComponentLifeCycle-test.js b/packages/react-dom/src/__tests__/ReactComponentLifeCycle-test.js
index cde3ab7a4f4f3..62ad2e01ba19d 100644
--- a/packages/react-dom/src/__tests__/ReactComponentLifeCycle-test.js
+++ b/packages/react-dom/src/__tests__/ReactComponentLifeCycle-test.js
@@ -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
;
+ }
+ }
+
+ expect(() => {
+ ReactTestUtils.renderIntoDocument();
+ }).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) {
diff --git a/packages/react-reconciler/src/ReactFiberClassComponent.js b/packages/react-reconciler/src/ReactFiberClassComponent.js
index 334bae2b72cc3..7646a51a70d12 100644
--- a/packages/react-reconciler/src/ReactFiberClassComponent.js
+++ b/packages/react-reconciler/src/ReactFiberClassComponent.js
@@ -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();
@@ -674,6 +676,20 @@ function mountClassInstance(
instance.context = getMaskedContext(workInProgress, unmaskedContext);
if (__DEV__) {
+ if (instance.state === instance.props) {
+ 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,