diff --git a/packages/react-dom/src/__tests__/ReactComponentLifeCycle-test.js b/packages/react-dom/src/__tests__/ReactComponentLifeCycle-test.js index fd286f1e68c8..7a370e32d129 100644 --- a/packages/react-dom/src/__tests__/ReactComponentLifeCycle-test.js +++ b/packages/react-dom/src/__tests__/ReactComponentLifeCycle-test.js @@ -709,9 +709,9 @@ describe('ReactComponentLifeCycle', () => { ); }).toLowPriorityWarnDev( [ - 'componentWillMount is deprecated', - 'componentWillReceiveProps is deprecated', - 'componentWillUpdate is deprecated', + 'componentWillMount has been renamed', + 'componentWillReceiveProps has been renamed', + 'componentWillUpdate has been renamed', ], {withoutStack: true}, ); @@ -748,9 +748,9 @@ describe('ReactComponentLifeCycle', () => { ); }).toLowPriorityWarnDev( [ - 'componentWillMount is deprecated', - 'componentWillReceiveProps is deprecated', - 'componentWillUpdate is deprecated', + 'componentWillMount has been renamed', + 'componentWillReceiveProps has been renamed', + 'componentWillUpdate has been renamed', ], {withoutStack: true}, ); @@ -815,7 +815,10 @@ describe('ReactComponentLifeCycle', () => { {withoutStack: true}, ); }).toLowPriorityWarnDev( - ['componentWillMount is deprecated', 'componentWillUpdate is deprecated'], + [ + 'componentWillMount has been renamed', + 'componentWillUpdate has been renamed', + ], {withoutStack: true}, ); @@ -863,7 +866,7 @@ describe('ReactComponentLifeCycle', () => { 'https://fb.me/react-async-component-lifecycle-hooks', {withoutStack: true}, ); - }).toLowPriorityWarnDev(['componentWillMount is deprecated'], { + }).toLowPriorityWarnDev(['componentWillMount has been renamed'], { withoutStack: true, }); @@ -887,7 +890,7 @@ describe('ReactComponentLifeCycle', () => { 'https://fb.me/react-async-component-lifecycle-hooks', {withoutStack: true}, ); - }).toLowPriorityWarnDev(['componentWillReceiveProps is deprecated'], { + }).toLowPriorityWarnDev(['componentWillReceiveProps has been renamed'], { withoutStack: true, }); }); @@ -921,7 +924,10 @@ describe('ReactComponentLifeCycle', () => { {withoutStack: true}, ); }).toLowPriorityWarnDev( - ['componentWillMount is deprecated', 'componentWillUpdate is deprecated'], + [ + 'componentWillMount has been renamed', + 'componentWillUpdate has been renamed', + ], {withoutStack: true}, ); @@ -967,7 +973,7 @@ describe('ReactComponentLifeCycle', () => { 'https://fb.me/react-async-component-lifecycle-hooks', {withoutStack: true}, ); - }).toLowPriorityWarnDev(['componentWillMount is deprecated'], { + }).toLowPriorityWarnDev(['componentWillMount has been renamed'], { withoutStack: true, }); @@ -990,7 +996,7 @@ describe('ReactComponentLifeCycle', () => { 'https://fb.me/react-async-component-lifecycle-hooks', {withoutStack: true}, ); - }).toLowPriorityWarnDev(['componentWillReceiveProps is deprecated'], { + }).toLowPriorityWarnDev(['componentWillReceiveProps has been renamed'], { withoutStack: true, }); }); @@ -1130,9 +1136,9 @@ describe('ReactComponentLifeCycle', () => { ReactDOM.render(, div), ).toLowPriorityWarnDev( [ - 'componentWillMount is deprecated', - 'componentWillReceiveProps is deprecated', - 'componentWillUpdate is deprecated', + 'componentWillMount has been renamed', + 'componentWillReceiveProps has been renamed', + 'componentWillUpdate has been renamed', ], {withoutStack: true}, ); @@ -1403,22 +1409,32 @@ describe('ReactComponentLifeCycle', () => { ReactDOM.render(, container), ).toLowPriorityWarnDev( [ - 'componentWillMount is deprecated and will be removed in the next major version. ' + - 'Use componentDidMount instead. As a temporary workaround, ' + - 'you can rename to UNSAFE_componentWillMount.' + - '\n\nPlease update the following components: MyComponent', - 'componentWillReceiveProps is deprecated and will be removed in the next major version. ' + - 'Use static getDerivedStateFromProps instead.' + - '\n\nPlease update the following components: MyComponent', - 'componentWillUpdate is deprecated and will be removed in the next major version. ' + - 'Use componentDidUpdate instead. As a temporary workaround, ' + - 'you can rename to UNSAFE_componentWillUpdate.' + - '\n\nPlease update the following components: MyComponent', + /* eslint-disable max-len */ + `Warning: componentWillMount has been renamed, and is not recommended for use. See https://fb.me/react-async-component-lifecycle-hooks for details. + +* Move code with side effects to componentDidMount, and set initial state in the constructor. +* Rename componentWillMount to UNSAFE_componentWillMount to suppress this warning in non-strict mode. In React 17.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, you can run \`npx react-codemod rename-unsafe-lifecycles\` in your project source folder. + +Please update the following components: MyComponent`, + `Warning: componentWillReceiveProps has been renamed, and is not recommended for use. See https://fb.me/react-async-component-lifecycle-hooks for details. + +* Move data fetching code or side effects to componentDidUpdate. +* If you're updating state whenever props change, refactor your code to use memoization techniques or move it to static getDerivedStateFromProps. Learn more at: https://fb.me/react-derived-state +* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress this warning in non-strict mode. In React 17.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, you can run \`npx react-codemod rename-unsafe-lifecycles\` in your project source folder. + +Please update the following components: MyComponent`, + `Warning: componentWillUpdate has been renamed, and is not recommended for use. See https://fb.me/react-async-component-lifecycle-hooks for details. + +* Move data fetching code or side effects to componentDidUpdate. +* Rename componentWillUpdate to UNSAFE_componentWillUpdate to suppress this warning in non-strict mode. In React 17.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, you can run \`npx react-codemod rename-unsafe-lifecycles\` in your project source folder. + +Please update the following components: MyComponent`, + /* eslint-enable max-len */ ], {withoutStack: true}, ); - // Dedupe check (update and instantiate new + // Dedupe check (update and instantiate new) ReactDOM.render(, container); ReactDOM.render(, container); }); diff --git a/packages/react-dom/src/__tests__/ReactDOMServerLifecycles-test.js b/packages/react-dom/src/__tests__/ReactDOMServerLifecycles-test.js index 76230a323035..4aed0e0246a6 100644 --- a/packages/react-dom/src/__tests__/ReactDOMServerLifecycles-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMServerLifecycles-test.js @@ -229,7 +229,7 @@ describe('ReactDOMServerLifecycles', () => { expect(() => ReactDOMServer.renderToString(), - ).toLowPriorityWarnDev('componentWillMount() is deprecated', { + ).toLowPriorityWarnDev('componentWillMount has been renamed', { withoutStack: true, }); expect(log).toEqual(['componentWillMount', 'UNSAFE_componentWillMount']); @@ -286,10 +286,9 @@ describe('ReactDOMServerLifecycles', () => { expect(() => ReactDOMServer.renderToString(), - ).toLowPriorityWarnDev( - 'Component: componentWillMount() is deprecated and will be removed in the next major version.', - {withoutStack: true}, - ); + ).toLowPriorityWarnDev('componentWillMount has been renamed', { + withoutStack: true, + }); }); it('should warn about deprecated lifecycle hooks', () => { @@ -302,11 +301,9 @@ describe('ReactDOMServerLifecycles', () => { expect(() => ReactDOMServer.renderToString(), - ).toLowPriorityWarnDev( - 'Warning: Component: componentWillMount() is deprecated and will be removed ' + - 'in the next major version.', - {withoutStack: true}, - ); + ).toLowPriorityWarnDev('componentWillMount has been renamed', { + withoutStack: true, + }); // De-duped ReactDOMServer.renderToString(); diff --git a/packages/react-dom/src/__tests__/ReactServerRenderingHydration-test.js b/packages/react-dom/src/__tests__/ReactServerRenderingHydration-test.js index 38d300debd14..d093a11bf8ab 100644 --- a/packages/react-dom/src/__tests__/ReactServerRenderingHydration-test.js +++ b/packages/react-dom/src/__tests__/ReactServerRenderingHydration-test.js @@ -362,20 +362,16 @@ describe('ReactDOMServerHydration', () => { const element = document.createElement('div'); expect(() => { element.innerHTML = ReactDOMServer.renderToString(markup); - }).toLowPriorityWarnDev( - ['componentWillMount() is deprecated and will be removed'], - {withoutStack: true}, - ); + }).toLowPriorityWarnDev(['componentWillMount has been renamed'], { + withoutStack: true, + }); expect(element.textContent).toBe('Hi'); expect(() => { - expect(() => ReactDOM.hydrate(markup, element)).toWarnDev( - 'Please update the following components to use componentDidMount instead: ComponentWithWarning', - ); - }).toLowPriorityWarnDev( - ['componentWillMount is deprecated and will be removed'], - {withoutStack: true}, - ); + ReactDOM.hydrate(markup, element); + }).toLowPriorityWarnDev(['componentWillMount has been renamed'], { + withoutStack: true, + }); expect(element.textContent).toBe('Hi'); }); diff --git a/packages/react-dom/src/server/ReactPartialRenderer.js b/packages/react-dom/src/server/ReactPartialRenderer.js index fdc7e17b3aa1..34c95ec25cc2 100644 --- a/packages/react-dom/src/server/ReactPartialRenderer.js +++ b/packages/react-dom/src/server/ReactPartialRenderer.js @@ -572,13 +572,12 @@ function resolve( if (!didWarnAboutDeprecatedWillMount[componentName]) { lowPriorityWarning( false, - '%s: componentWillMount() is deprecated and will be ' + - 'removed in the next major version. Read about the motivations ' + - 'behind this change: ' + - 'https://fb.me/react-async-component-lifecycle-hooks' + - '\n\n' + - 'As a temporary workaround, you can rename to ' + - 'UNSAFE_componentWillMount instead.', + // keep this warning in sync with ReactStrictModeWarning.js + 'componentWillMount has been renamed, and is not recommended for use. ' + + 'See https://fb.me/react-async-component-lifecycle-hooks for details.\n\n' + + '* Move code from componentWillMount to componentDidMount (preferred in most cases) ' + + 'or the constructor.\n' + + '\nPlease update the following components: %s', componentName, ); didWarnAboutDeprecatedWillMount[componentName] = true; diff --git a/packages/react-reconciler/src/ReactFiberClassComponent.js b/packages/react-reconciler/src/ReactFiberClassComponent.js index 369b01dbca35..fcadf0a22ce8 100644 --- a/packages/react-reconciler/src/ReactFiberClassComponent.js +++ b/packages/react-reconciler/src/ReactFiberClassComponent.js @@ -806,11 +806,6 @@ function mountClassInstance( } if (workInProgress.mode & StrictMode) { - ReactStrictModeWarnings.recordUnsafeLifecycleWarnings( - workInProgress, - instance, - ); - ReactStrictModeWarnings.recordLegacyContextWarning( workInProgress, instance, @@ -818,7 +813,7 @@ function mountClassInstance( } if (warnAboutDeprecatedLifecycles) { - ReactStrictModeWarnings.recordDeprecationWarnings( + ReactStrictModeWarnings.recordUnsafeLifecycleWarnings( workInProgress, instance, ); diff --git a/packages/react-reconciler/src/ReactFiberWorkLoop.js b/packages/react-reconciler/src/ReactFiberWorkLoop.js index b05e42a5512d..1c291d0b8745 100644 --- a/packages/react-reconciler/src/ReactFiberWorkLoop.js +++ b/packages/react-reconciler/src/ReactFiberWorkLoop.js @@ -2247,11 +2247,10 @@ function checkForNestedUpdates() { function flushRenderPhaseStrictModeWarningsInDEV() { if (__DEV__) { - ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings(); ReactStrictModeWarnings.flushLegacyContextWarning(); if (warnAboutDeprecatedLifecycles) { - ReactStrictModeWarnings.flushPendingDeprecationWarnings(); + ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings(); } } } diff --git a/packages/react-reconciler/src/ReactStrictModeWarnings.js b/packages/react-reconciler/src/ReactStrictModeWarnings.js index 143e7ebd4a7b..3fbfc06d93d9 100644 --- a/packages/react-reconciler/src/ReactStrictModeWarnings.js +++ b/packages/react-reconciler/src/ReactStrictModeWarnings.js @@ -16,105 +16,18 @@ import {StrictMode} from './ReactTypeOfMode'; import lowPriorityWarning from 'shared/lowPriorityWarning'; import warningWithoutStack from 'shared/warningWithoutStack'; -type LIFECYCLE = - | 'UNSAFE_componentWillMount' - | 'UNSAFE_componentWillReceiveProps' - | 'UNSAFE_componentWillUpdate'; -type LifecycleToComponentsMap = {[lifecycle: LIFECYCLE]: Array}; -type FiberToLifecycleMap = Map; type FiberArray = Array; type FiberToFiberComponentsMap = Map; const ReactStrictModeWarnings = { - discardPendingWarnings(): void {}, - flushPendingDeprecationWarnings(): void {}, - flushPendingUnsafeLifecycleWarnings(): void {}, - recordDeprecationWarnings(fiber: Fiber, instance: any): void {}, recordUnsafeLifecycleWarnings(fiber: Fiber, instance: any): void {}, + flushPendingUnsafeLifecycleWarnings(): void {}, recordLegacyContextWarning(fiber: Fiber, instance: any): void {}, flushLegacyContextWarning(): void {}, + discardPendingWarnings(): void {}, }; if (__DEV__) { - const LIFECYCLE_SUGGESTIONS = { - UNSAFE_componentWillMount: 'componentDidMount', - UNSAFE_componentWillReceiveProps: 'static getDerivedStateFromProps', - UNSAFE_componentWillUpdate: 'componentDidUpdate', - }; - - let pendingComponentWillMountWarnings: Array = []; - let pendingComponentWillReceivePropsWarnings: Array = []; - let pendingComponentWillUpdateWarnings: Array = []; - let pendingUnsafeLifecycleWarnings: FiberToLifecycleMap = new Map(); - let pendingLegacyContextWarning: FiberToFiberComponentsMap = new Map(); - - // Tracks components we have already warned about. - const didWarnAboutDeprecatedLifecycles = new Set(); - const didWarnAboutUnsafeLifecycles = new Set(); - const didWarnAboutLegacyContext = new Set(); - - const setToSortedString = set => { - const array = []; - set.forEach(value => { - array.push(value); - }); - return array.sort().join(', '); - }; - - ReactStrictModeWarnings.discardPendingWarnings = () => { - pendingComponentWillMountWarnings = []; - pendingComponentWillReceivePropsWarnings = []; - pendingComponentWillUpdateWarnings = []; - pendingUnsafeLifecycleWarnings = new Map(); - pendingLegacyContextWarning = new Map(); - }; - - ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings = () => { - ((pendingUnsafeLifecycleWarnings: any): FiberToLifecycleMap).forEach( - (lifecycleWarningsMap, strictRoot) => { - const lifecyclesWarningMessages = []; - - Object.keys(lifecycleWarningsMap).forEach(lifecycle => { - const lifecycleWarnings = lifecycleWarningsMap[lifecycle]; - if (lifecycleWarnings.length > 0) { - const componentNames = new Set(); - lifecycleWarnings.forEach(fiber => { - componentNames.add(getComponentName(fiber.type) || 'Component'); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - - const formatted = lifecycle.replace('UNSAFE_', ''); - const suggestion = LIFECYCLE_SUGGESTIONS[lifecycle]; - const sortedComponentNames = setToSortedString(componentNames); - - lifecyclesWarningMessages.push( - `${formatted}: Please update the following components to use ` + - `${suggestion} instead: ${sortedComponentNames}`, - ); - } - }); - - if (lifecyclesWarningMessages.length > 0) { - const strictRootComponentStack = getStackByFiberInDevAndProd( - strictRoot, - ); - - warningWithoutStack( - false, - 'Unsafe lifecycle methods were found within a strict-mode tree:%s' + - '\n\n%s' + - '\n\nLearn more about this warning here:' + - '\nhttps://fb.me/react-strict-mode-warnings', - strictRootComponentStack, - lifecyclesWarningMessages.join('\n\n'), - ); - } - }, - ); - - pendingUnsafeLifecycleWarnings = new Map(); - }; - const findStrictRoot = (fiber: Fiber): Fiber | null => { let maybeStrictRoot = null; @@ -129,175 +42,260 @@ if (__DEV__) { return maybeStrictRoot; }; - ReactStrictModeWarnings.flushPendingDeprecationWarnings = () => { - if (pendingComponentWillMountWarnings.length > 0) { - const uniqueNames = new Set(); - pendingComponentWillMountWarnings.forEach(fiber => { - uniqueNames.add(getComponentName(fiber.type) || 'Component'); - didWarnAboutDeprecatedLifecycles.add(fiber.type); - }); - - const sortedNames = setToSortedString(uniqueNames); - - lowPriorityWarning( - false, - 'componentWillMount is deprecated and will be removed in the next major version. ' + - 'Use componentDidMount instead. As a temporary workaround, ' + - 'you can rename to UNSAFE_componentWillMount.' + - '\n\nPlease update the following components: %s' + - '\n\nLearn more about this warning here:' + - '\nhttps://fb.me/react-async-component-lifecycle-hooks', - sortedNames, - ); - - pendingComponentWillMountWarnings = []; - } - - if (pendingComponentWillReceivePropsWarnings.length > 0) { - const uniqueNames = new Set(); - pendingComponentWillReceivePropsWarnings.forEach(fiber => { - uniqueNames.add(getComponentName(fiber.type) || 'Component'); - didWarnAboutDeprecatedLifecycles.add(fiber.type); - }); - - const sortedNames = setToSortedString(uniqueNames); - - lowPriorityWarning( - false, - 'componentWillReceiveProps is deprecated and will be removed in the next major version. ' + - 'Use static getDerivedStateFromProps instead.' + - '\n\nPlease update the following components: %s' + - '\n\nLearn more about this warning here:' + - '\nhttps://fb.me/react-async-component-lifecycle-hooks', - sortedNames, - ); - - pendingComponentWillReceivePropsWarnings = []; - } - - if (pendingComponentWillUpdateWarnings.length > 0) { - const uniqueNames = new Set(); - pendingComponentWillUpdateWarnings.forEach(fiber => { - uniqueNames.add(getComponentName(fiber.type) || 'Component'); - didWarnAboutDeprecatedLifecycles.add(fiber.type); - }); - - const sortedNames = setToSortedString(uniqueNames); + const setToSortedString = set => { + const array = []; + set.forEach(value => { + array.push(value); + }); + return array.sort().join(', '); + }; - lowPriorityWarning( - false, - 'componentWillUpdate is deprecated and will be removed in the next major version. ' + - 'Use componentDidUpdate instead. As a temporary workaround, ' + - 'you can rename to UNSAFE_componentWillUpdate.' + - '\n\nPlease update the following components: %s' + - '\n\nLearn more about this warning here:' + - '\nhttps://fb.me/react-async-component-lifecycle-hooks', - sortedNames, - ); + let pendingComponentWillMountWarnings: Array = []; + let pendingUNSAFE_ComponentWillMountWarnings: Array = []; + let pendingComponentWillReceivePropsWarnings: Array = []; + let pendingUNSAFE_ComponentWillReceivePropsWarnings: Array = []; + let pendingComponentWillUpdateWarnings: Array = []; + let pendingUNSAFE_ComponentWillUpdateWarnings: Array = []; - pendingComponentWillUpdateWarnings = []; - } - }; + // Tracks components we have already warned about. + const didWarnAboutUnsafeLifecycles = new Set(); - ReactStrictModeWarnings.recordDeprecationWarnings = ( + ReactStrictModeWarnings.recordUnsafeLifecycleWarnings = ( fiber: Fiber, instance: any, ) => { // Dedup strategy: Warn once per component. - if (didWarnAboutDeprecatedLifecycles.has(fiber.type)) { + if (didWarnAboutUnsafeLifecycles.has(fiber.type)) { return; } - // Don't warn about react-lifecycles-compat polyfilled components. if ( typeof instance.componentWillMount === 'function' && + // Don't warn about react-lifecycles-compat polyfilled components. instance.componentWillMount.__suppressDeprecationWarning !== true ) { pendingComponentWillMountWarnings.push(fiber); } + + if ( + fiber.mode & StrictMode && + typeof instance.UNSAFE_componentWillMount === 'function' + ) { + pendingUNSAFE_ComponentWillMountWarnings.push(fiber); + } + if ( typeof instance.componentWillReceiveProps === 'function' && instance.componentWillReceiveProps.__suppressDeprecationWarning !== true ) { pendingComponentWillReceivePropsWarnings.push(fiber); } + + if ( + fiber.mode & StrictMode && + typeof instance.UNSAFE_componentWillReceiveProps === 'function' + ) { + pendingUNSAFE_ComponentWillReceivePropsWarnings.push(fiber); + } + if ( typeof instance.componentWillUpdate === 'function' && instance.componentWillUpdate.__suppressDeprecationWarning !== true ) { pendingComponentWillUpdateWarnings.push(fiber); } + + if ( + fiber.mode & StrictMode && + typeof instance.UNSAFE_componentWillUpdate === 'function' + ) { + pendingUNSAFE_ComponentWillUpdateWarnings.push(fiber); + } }; - ReactStrictModeWarnings.recordUnsafeLifecycleWarnings = ( - fiber: Fiber, - instance: any, - ) => { - const strictRoot = findStrictRoot(fiber); - if (strictRoot === null) { + ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings = () => { + // We do an initial pass to gather component names + const componentWillMountUniqueNames = new Set(); + if (pendingComponentWillMountWarnings.length > 0) { + pendingComponentWillMountWarnings.forEach(fiber => { + componentWillMountUniqueNames.add( + getComponentName(fiber.type) || 'Component', + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingComponentWillMountWarnings = []; + } + + const UNSAFE_componentWillMountUniqueNames = new Set(); + if (pendingUNSAFE_ComponentWillMountWarnings.length > 0) { + pendingUNSAFE_ComponentWillMountWarnings.forEach(fiber => { + UNSAFE_componentWillMountUniqueNames.add( + getComponentName(fiber.type) || 'Component', + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingUNSAFE_ComponentWillMountWarnings = []; + } + + const componentWillReceivePropsUniqueNames = new Set(); + if (pendingComponentWillReceivePropsWarnings.length > 0) { + pendingComponentWillReceivePropsWarnings.forEach(fiber => { + componentWillReceivePropsUniqueNames.add( + getComponentName(fiber.type) || 'Component', + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + + pendingComponentWillReceivePropsWarnings = []; + } + + const UNSAFE_componentWillReceivePropsUniqueNames = new Set(); + if (pendingUNSAFE_ComponentWillReceivePropsWarnings.length > 0) { + pendingUNSAFE_ComponentWillReceivePropsWarnings.forEach(fiber => { + UNSAFE_componentWillReceivePropsUniqueNames.add( + getComponentName(fiber.type) || 'Component', + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + + pendingUNSAFE_ComponentWillReceivePropsWarnings = []; + } + + const componentWillUpdateUniqueNames = new Set(); + if (pendingComponentWillUpdateWarnings.length > 0) { + pendingComponentWillUpdateWarnings.forEach(fiber => { + componentWillUpdateUniqueNames.add( + getComponentName(fiber.type) || 'Component', + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + + pendingComponentWillUpdateWarnings = []; + } + + const UNSAFE_componentWillUpdateUniqueNames = new Set(); + if (pendingUNSAFE_ComponentWillUpdateWarnings.length > 0) { + pendingUNSAFE_ComponentWillUpdateWarnings.forEach(fiber => { + UNSAFE_componentWillUpdateUniqueNames.add( + getComponentName(fiber.type) || 'Component', + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + + pendingUNSAFE_ComponentWillUpdateWarnings = []; + } + + // Finally, we flush all the warnings + // UNSAFE_ ones before the deprecated ones, since they'll be 'louder' + if (UNSAFE_componentWillMountUniqueNames.size > 0) { + const sortedNames = setToSortedString( + UNSAFE_componentWillMountUniqueNames, + ); warningWithoutStack( false, - 'Expected to find a StrictMode component in a strict mode tree. ' + - 'This error is likely caused by a bug in React. Please file an issue.', + 'Using UNSAFE_componentWillMount in strict mode is not recommended and may indicate bugs in your code. ' + + 'See https://fb.me/react-async-component-lifecycle-hooks for details.\n\n' + + '* Move code with side effects to componentDidMount, and set initial state in the constructor.\n' + + '\nPlease update the following components: %s', + sortedNames, ); - return; } - // Dedup strategy: Warn once per component. - // This is difficult to track any other way since component names - // are often vague and are likely to collide between 3rd party libraries. - // An expand property is probably okay to use here since it's DEV-only, - // and will only be set in the event of serious warnings. - if (didWarnAboutUnsafeLifecycles.has(fiber.type)) { - return; + if (UNSAFE_componentWillReceivePropsUniqueNames.size > 0) { + const sortedNames = setToSortedString( + UNSAFE_componentWillReceivePropsUniqueNames, + ); + warningWithoutStack( + false, + 'Using UNSAFE_componentWillReceiveProps in strict mode is not recommended ' + + 'and may indicate bugs in your code. ' + + 'See https://fb.me/react-async-component-lifecycle-hooks for details.\n\n' + + '* Move data fetching code or side effects to componentDidUpdate.\n' + + "* If you're updating state whenever props change, " + + 'refactor your code to use memoization techniques or move it to ' + + 'static getDerivedStateFromProps. Learn more at: https://fb.me/react-derived-state\n' + + '\nPlease update the following components: %s', + sortedNames, + ); } - let warningsForRoot; - if (!pendingUnsafeLifecycleWarnings.has(strictRoot)) { - warningsForRoot = { - UNSAFE_componentWillMount: [], - UNSAFE_componentWillReceiveProps: [], - UNSAFE_componentWillUpdate: [], - }; - - pendingUnsafeLifecycleWarnings.set(strictRoot, warningsForRoot); - } else { - warningsForRoot = pendingUnsafeLifecycleWarnings.get(strictRoot); + if (UNSAFE_componentWillUpdateUniqueNames.size > 0) { + const sortedNames = setToSortedString( + UNSAFE_componentWillUpdateUniqueNames, + ); + warningWithoutStack( + false, + 'Using UNSAFE_componentWillUpdate in strict mode is not recommended ' + + 'and may indicate bugs in your code. ' + + 'See https://fb.me/react-async-component-lifecycle-hooks for details.\n\n' + + '* Move data fetching code or side effects to componentDidUpdate.\n' + + '\nPlease update the following components: %s', + sortedNames, + ); } - const unsafeLifecycles = []; - if ( - (typeof instance.componentWillMount === 'function' && - instance.componentWillMount.__suppressDeprecationWarning !== true) || - typeof instance.UNSAFE_componentWillMount === 'function' - ) { - unsafeLifecycles.push('UNSAFE_componentWillMount'); - } - if ( - (typeof instance.componentWillReceiveProps === 'function' && - instance.componentWillReceiveProps.__suppressDeprecationWarning !== - true) || - typeof instance.UNSAFE_componentWillReceiveProps === 'function' - ) { - unsafeLifecycles.push('UNSAFE_componentWillReceiveProps'); + if (componentWillMountUniqueNames.size > 0) { + const sortedNames = setToSortedString(componentWillMountUniqueNames); + + lowPriorityWarning( + false, + 'componentWillMount has been renamed, and is not recommended for use. ' + + 'See https://fb.me/react-async-component-lifecycle-hooks for details.\n\n' + + '* Move code with side effects to componentDidMount, and set initial state in the constructor.\n' + + '* Rename componentWillMount to UNSAFE_componentWillMount to suppress ' + + 'this warning in non-strict mode. In React 17.x, only the UNSAFE_ name will work. ' + + 'To rename all deprecated lifecycles to their new names, you can run ' + + '`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n' + + '\nPlease update the following components: %s', + sortedNames, + ); } - if ( - (typeof instance.componentWillUpdate === 'function' && - instance.componentWillUpdate.__suppressDeprecationWarning !== true) || - typeof instance.UNSAFE_componentWillUpdate === 'function' - ) { - unsafeLifecycles.push('UNSAFE_componentWillUpdate'); + + if (componentWillReceivePropsUniqueNames.size > 0) { + const sortedNames = setToSortedString( + componentWillReceivePropsUniqueNames, + ); + + lowPriorityWarning( + false, + 'componentWillReceiveProps has been renamed, and is not recommended for use. ' + + 'See https://fb.me/react-async-component-lifecycle-hooks for details.\n\n' + + '* Move data fetching code or side effects to componentDidUpdate.\n' + + "* If you're updating state whenever props change, refactor your " + + 'code to use memoization techniques or move it to ' + + 'static getDerivedStateFromProps. Learn more at: https://fb.me/react-derived-state\n' + + '* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress ' + + 'this warning in non-strict mode. In React 17.x, only the UNSAFE_ name will work. ' + + 'To rename all deprecated lifecycles to their new names, you can run ' + + '`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n' + + '\nPlease update the following components: %s', + sortedNames, + ); } - if (unsafeLifecycles.length > 0) { - unsafeLifecycles.forEach(lifecycle => { - ((warningsForRoot: any): LifecycleToComponentsMap)[lifecycle].push( - fiber, - ); - }); + if (componentWillUpdateUniqueNames.size > 0) { + const sortedNames = setToSortedString(componentWillUpdateUniqueNames); + + lowPriorityWarning( + false, + 'componentWillUpdate has been renamed, and is not recommended for use. ' + + 'See https://fb.me/react-async-component-lifecycle-hooks for details.\n\n' + + '* Move data fetching code or side effects to componentDidUpdate.\n' + + '* Rename componentWillUpdate to UNSAFE_componentWillUpdate to suppress ' + + 'this warning in non-strict mode. In React 17.x, only the UNSAFE_ name will work. ' + + 'To rename all deprecated lifecycles to their new names, you can run ' + + '`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n' + + '\nPlease update the following components: %s', + sortedNames, + ); } }; + let pendingLegacyContextWarning: FiberToFiberComponentsMap = new Map(); + + // Tracks components we have already warned about. + const didWarnAboutLegacyContext = new Set(); + ReactStrictModeWarnings.recordLegacyContextWarning = ( fiber: Fiber, instance: any, @@ -358,6 +356,16 @@ if (__DEV__) { }, ); }; + + ReactStrictModeWarnings.discardPendingWarnings = () => { + pendingComponentWillMountWarnings = []; + pendingUNSAFE_ComponentWillMountWarnings = []; + pendingComponentWillReceivePropsWarnings = []; + pendingUNSAFE_ComponentWillReceivePropsWarnings = []; + pendingComponentWillUpdateWarnings = []; + pendingUNSAFE_ComponentWillUpdateWarnings = []; + pendingLegacyContextWarning = new Map(); + }; } export default ReactStrictModeWarnings; diff --git a/packages/react-reconciler/src/__tests__/ReactIncremental-test.internal.js b/packages/react-reconciler/src/__tests__/ReactIncremental-test.internal.js index 6557eb0b1dc8..89e2052b10f6 100644 --- a/packages/react-reconciler/src/__tests__/ReactIncremental-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactIncremental-test.internal.js @@ -2446,8 +2446,7 @@ describe('ReactIncremental', () => { ReactNoop.render(); expect(() => expect(Scheduler).toFlushWithoutYielding()).toWarnDev( [ - 'componentWillReceiveProps: Please update the following components ' + - 'to use static getDerivedStateFromProps instead: MyComponent', + 'Using UNSAFE_componentWillReceiveProps in strict mode is not recommended', 'Legacy context API has been detected within a strict-mode tree: \n\n' + 'Please update the following components: MyComponent', ], @@ -2887,8 +2886,7 @@ describe('ReactIncremental', () => { expect(Scheduler).toFlushAndYield([]); }); - // We don't currently use fibers as keys. Re-enable this test if we - // ever do again. + // We sometimes use Maps with Fibers as keys. it('does not break with a bad Map polyfill', () => { const realMapSet = Map.prototype.set; @@ -2896,17 +2894,27 @@ describe('ReactIncremental', () => { function Thing() { throw new Error('No.'); } + // This class uses legacy context, which triggers warnings, + // the procedures for which use a Map to store fibers. class Boundary extends React.Component { state = {didError: false}; componentDidCatch() { this.setState({didError: true}); } + static contextTypes = { + color: () => null, + }; render() { return this.state.didError ? null : ; } } ReactNoop.render(); - expect(Scheduler).toFlushWithoutYielding(); + expect(() => { + expect(Scheduler).toFlushWithoutYielding(); + }).toWarnDev( + ['Legacy context API has been detected within a strict-mode tree'], + {withoutStack: true}, + ); } // First, verify that this code path normally receives Fibers as keys, @@ -2952,6 +2960,7 @@ describe('ReactIncremental', () => { }; React = require('react'); ReactNoop = require('react-noop-renderer'); + Scheduler = require('scheduler'); try { triggerCodePathThatUsesFibersAsMapKeys(); } finally { diff --git a/packages/react-reconciler/src/__tests__/ReactIncrementalPerf-test.internal.js b/packages/react-reconciler/src/__tests__/ReactIncrementalPerf-test.internal.js index fb01a550a114..b6b957647e04 100644 --- a/packages/react-reconciler/src/__tests__/ReactIncrementalPerf-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactIncrementalPerf-test.internal.js @@ -316,10 +316,8 @@ describe('ReactDebugFiberPerf', () => { addComment('Should not print a warning'); expect(() => expect(Scheduler).toFlushWithoutYielding()).toWarnDev( [ - 'componentWillMount: Please update the following components ' + - 'to use componentDidMount instead: NotCascading' + - '\n\ncomponentWillReceiveProps: Please update the following components ' + - 'to use static getDerivedStateFromProps instead: NotCascading', + 'Using UNSAFE_componentWillMount in strict mode is not recommended', + 'Using UNSAFE_componentWillReceiveProps in strict mode is not recommended', ], {withoutStack: true}, ); @@ -358,14 +356,10 @@ describe('ReactDebugFiberPerf', () => { addComment('Mount'); expect(() => expect(Scheduler).toFlushWithoutYielding()).toWarnDev( [ - 'componentWillMount: Please update the following components ' + - 'to use componentDidMount instead: AllLifecycles' + - '\n\ncomponentWillReceiveProps: Please update the following components ' + - 'to use static getDerivedStateFromProps instead: AllLifecycles' + - '\n\ncomponentWillUpdate: Please update the following components ' + - 'to use componentDidUpdate instead: AllLifecycles', - 'Legacy context API has been detected within a strict-mode tree: \n\n' + - 'Please update the following components: AllLifecycles', + 'Using UNSAFE_componentWillMount in strict mode is not recommended', + 'Using UNSAFE_componentWillReceiveProps in strict mode is not recommended', + 'Using UNSAFE_componentWillUpdate in strict mode is not recommended', + 'Legacy context API has been detected within a strict-mode tree', ], {withoutStack: true}, ); diff --git a/packages/react-reconciler/src/__tests__/ReactIncrementalReflection-test.internal.js b/packages/react-reconciler/src/__tests__/ReactIncrementalReflection-test.internal.js index e161942a2986..cf57910c7a53 100644 --- a/packages/react-reconciler/src/__tests__/ReactIncrementalReflection-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactIncrementalReflection-test.internal.js @@ -76,8 +76,7 @@ describe('ReactIncrementalReflection', () => { expect(() => expect(Scheduler).toFlushAndYield(['componentDidMount: true']), ).toWarnDev( - 'componentWillMount: Please update the following components ' + - 'to use componentDidMount instead: Component', + 'Using UNSAFE_componentWillMount in strict mode is not recommended', {withoutStack: true}, ); @@ -116,8 +115,7 @@ describe('ReactIncrementalReflection', () => { ReactNoop.render(); expect(() => expect(Scheduler).toFlushAndYield(['Component'])).toWarnDev( - 'componentWillMount: Please update the following components ' + - 'to use componentDidMount instead: Component', + 'Using UNSAFE_componentWillMount in strict mode is not recommended', {withoutStack: true}, ); @@ -222,10 +220,10 @@ describe('ReactIncrementalReflection', () => { expect(() => expect(Scheduler).toFlushAndYield([['componentDidMount', span()]]), ).toWarnDev( - 'componentWillMount: Please update the following components ' + - 'to use componentDidMount instead: Component' + - '\n\ncomponentWillUpdate: Please update the following components ' + - 'to use componentDidUpdate instead: Component', + [ + 'Using UNSAFE_componentWillMount in strict mode is not recommended', + 'Using UNSAFE_componentWillUpdate in strict mode is not recommended', + ], {withoutStack: true}, ); diff --git a/packages/react-reconciler/src/__tests__/ReactIncrementalUpdates-test.internal.js b/packages/react-reconciler/src/__tests__/ReactIncrementalUpdates-test.internal.js index 58dac988901a..ccb71f60dfbe 100644 --- a/packages/react-reconciler/src/__tests__/ReactIncrementalUpdates-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactIncrementalUpdates-test.internal.js @@ -346,8 +346,7 @@ describe('ReactIncrementalUpdates', () => { } ReactNoop.render(); expect(() => expect(Scheduler).toFlushWithoutYielding()).toWarnDev( - 'componentWillReceiveProps: Please update the following components ' + - 'to use static getDerivedStateFromProps instead: Foo', + 'Using UNSAFE_componentWillReceiveProps in strict mode is not recommended', {withoutStack: true}, ); diff --git a/packages/react/src/__tests__/ReactStrictMode-test.internal.js b/packages/react/src/__tests__/ReactStrictMode-test.internal.js index d64781dc6bcc..96fec421de74 100644 --- a/packages/react/src/__tests__/ReactStrictMode-test.internal.js +++ b/packages/react/src/__tests__/ReactStrictMode-test.internal.js @@ -349,15 +349,26 @@ describe('ReactStrictMode', () => { }); root.update(); expect(() => Scheduler.unstable_flushAll()).toWarnDev( - 'Unsafe lifecycle methods were found within a strict-mode tree:' + - '\n\ncomponentWillMount: Please update the following components ' + - 'to use componentDidMount instead: AsyncRoot' + - '\n\ncomponentWillReceiveProps: Please update the following components ' + - 'to use static getDerivedStateFromProps instead: Bar, Foo' + - '\n\ncomponentWillUpdate: Please update the following components ' + - 'to use componentDidUpdate instead: AsyncRoot' + - '\n\nLearn more about this warning here:' + - '\nhttps://fb.me/react-strict-mode-warnings', + [ + /* eslint-disable max-len */ + `Warning: Using UNSAFE_componentWillMount in strict mode is not recommended and may indicate bugs in your code. See https://fb.me/react-async-component-lifecycle-hooks for details. + +* Move code with side effects to componentDidMount, and set initial state in the constructor. + +Please update the following components: AsyncRoot`, + `Warning: Using UNSAFE_componentWillReceiveProps in strict mode is not recommended and may indicate bugs in your code. See https://fb.me/react-async-component-lifecycle-hooks for details. + +* Move data fetching code or side effects to componentDidUpdate. +* If you're updating state whenever props change, refactor your code to use memoization techniques or move it to static getDerivedStateFromProps. Learn more at: https://fb.me/react-derived-state + +Please update the following components: Bar, Foo`, + `Warning: Using UNSAFE_componentWillUpdate in strict mode is not recommended and may indicate bugs in your code. See https://fb.me/react-async-component-lifecycle-hooks for details. + +* Move data fetching code or side effects to componentDidUpdate. + +Please update the following components: AsyncRoot`, + /* eslint-enable max-len */ + ], {withoutStack: true}, ); @@ -396,26 +407,54 @@ describe('ReactStrictMode', () => { expect(() => { expect(() => Scheduler.unstable_flushAll()).toWarnDev( - 'Unsafe lifecycle methods were found within a strict-mode tree:' + - '\n\ncomponentWillMount: Please update the following components ' + - 'to use componentDidMount instead: AsyncRoot, Parent' + - '\n\ncomponentWillReceiveProps: Please update the following components ' + - 'to use static getDerivedStateFromProps instead: Child, Parent' + - '\n\ncomponentWillUpdate: Please update the following components ' + - 'to use componentDidUpdate instead: AsyncRoot, Parent' + - '\n\nLearn more about this warning here:' + - '\nhttps://fb.me/react-strict-mode-warnings', + [ + /* eslint-disable max-len */ + `Warning: Using UNSAFE_componentWillMount in strict mode is not recommended and may indicate bugs in your code. See https://fb.me/react-async-component-lifecycle-hooks for details. + +* Move code with side effects to componentDidMount, and set initial state in the constructor. + +Please update the following components: AsyncRoot`, + `Warning: Using UNSAFE_componentWillReceiveProps in strict mode is not recommended and may indicate bugs in your code. See https://fb.me/react-async-component-lifecycle-hooks for details. + +* Move data fetching code or side effects to componentDidUpdate. +* If you're updating state whenever props change, refactor your code to use memoization techniques or move it to static getDerivedStateFromProps. Learn more at: https://fb.me/react-derived-state + +Please update the following components: Child`, + `Warning: Using UNSAFE_componentWillUpdate in strict mode is not recommended and may indicate bugs in your code. See https://fb.me/react-async-component-lifecycle-hooks for details. + +* Move data fetching code or side effects to componentDidUpdate. + +Please update the following components: AsyncRoot`, + /* eslint-enable max-len */ + ], {withoutStack: true}, ); }).toLowPriorityWarnDev( [ - 'componentWillMount is deprecated', - 'componentWillReceiveProps is deprecated', - 'componentWillUpdate is deprecated', + /* eslint-disable max-len */ + `Warning: componentWillMount has been renamed, and is not recommended for use. See https://fb.me/react-async-component-lifecycle-hooks for details. + +* Move code with side effects to componentDidMount, and set initial state in the constructor. +* Rename componentWillMount to UNSAFE_componentWillMount to suppress this warning in non-strict mode. In React 17.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, you can run \`npx react-codemod rename-unsafe-lifecycles\` in your project source folder. + +Please update the following components: Parent`, + `Warning: componentWillReceiveProps has been renamed, and is not recommended for use. See https://fb.me/react-async-component-lifecycle-hooks for details. + +* Move data fetching code or side effects to componentDidUpdate. +* If you're updating state whenever props change, refactor your code to use memoization techniques or move it to static getDerivedStateFromProps. Learn more at: https://fb.me/react-derived-state +* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress this warning in non-strict mode. In React 17.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, you can run \`npx react-codemod rename-unsafe-lifecycles\` in your project source folder. + +Please update the following components: Parent`, + `Warning: componentWillUpdate has been renamed, and is not recommended for use. See https://fb.me/react-async-component-lifecycle-hooks for details. + +* Move data fetching code or side effects to componentDidUpdate. +* Rename componentWillUpdate to UNSAFE_componentWillUpdate to suppress this warning in non-strict mode. In React 17.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, you can run \`npx react-codemod rename-unsafe-lifecycles\` in your project source folder. + +Please update the following components: Parent`, + /* eslint-enable max-len */ ], {withoutStack: true}, ); - // Dedupe root.update(); Scheduler.unstable_flushAll(); @@ -445,21 +484,13 @@ describe('ReactStrictMode', () => { }); root.update(); expect(() => Scheduler.unstable_flushAll()).toWarnDev( - 'Unsafe lifecycle methods were found within a strict-mode tree:' + - '\n\ncomponentWillMount: Please update the following components ' + - 'to use componentDidMount instead: Foo' + - '\n\nLearn more about this warning here:' + - '\nhttps://fb.me/react-strict-mode-warnings', + 'Using UNSAFE_componentWillMount in strict mode is not recommended', {withoutStack: true}, ); root.update(); expect(() => Scheduler.unstable_flushAll()).toWarnDev( - 'Unsafe lifecycle methods were found within a strict-mode tree:' + - '\n\ncomponentWillMount: Please update the following components ' + - 'to use componentDidMount instead: Bar' + - '\n\nLearn more about this warning here:' + - '\nhttps://fb.me/react-strict-mode-warnings', + 'Using UNSAFE_componentWillMount in strict mode is not recommended', {withoutStack: true}, ); @@ -507,13 +538,8 @@ describe('ReactStrictMode', () => { } expect(() => ReactTestRenderer.create()).toWarnDev( - 'Unsafe lifecycle methods were found within a strict-mode tree:' + - '\n in StrictMode (at **)' + - '\n in SyncRoot (at **)' + - '\n\ncomponentWillReceiveProps: Please update the following components ' + - 'to use static getDerivedStateFromProps instead: Bar, Foo' + - '\n\nLearn more about this warning here:' + - '\nhttps://fb.me/react-strict-mode-warnings', + 'Using UNSAFE_componentWillReceiveProps in strict mode is not recommended', + {withoutStack: true}, ); // Dedupe diff --git a/packages/react/src/__tests__/createReactClassIntegration-test.internal.js b/packages/react/src/__tests__/createReactClassIntegration-test.internal.js index b1bd7c9b1c91..f6b7a955d513 100644 --- a/packages/react/src/__tests__/createReactClassIntegration-test.internal.js +++ b/packages/react/src/__tests__/createReactClassIntegration-test.internal.js @@ -51,10 +51,7 @@ describe('create-react-class-integration', () => { }); expect(() => ReactNative.render(, 1)).toLowPriorityWarnDev( - 'componentWillMount is deprecated and will be removed in the next major version. ' + - 'Use componentDidMount instead. As a temporary workaround, ' + - 'you can rename to UNSAFE_componentWillMount.' + - '\n\nPlease update the following components: MyNativeComponent', + 'componentWillMount has been renamed', {withoutStack: true}, ); }); @@ -68,9 +65,7 @@ describe('create-react-class-integration', () => { }); expect(() => ReactNative.render(, 1)).toLowPriorityWarnDev( - 'componentWillReceiveProps is deprecated and will be removed in the next major version. ' + - 'Use static getDerivedStateFromProps instead.' + - '\n\nPlease update the following components: MyNativeComponent', + 'componentWillReceiveProps has been renamed', {withoutStack: true}, ); }); diff --git a/packages/react/src/__tests__/createReactClassIntegration-test.js b/packages/react/src/__tests__/createReactClassIntegration-test.js index 36b6bb047732..542a35087033 100644 --- a/packages/react/src/__tests__/createReactClassIntegration-test.js +++ b/packages/react/src/__tests__/createReactClassIntegration-test.js @@ -560,9 +560,9 @@ describe('create-react-class-integration', () => { ); }).toLowPriorityWarnDev( [ - 'componentWillMount is deprecated', - 'componentWillReceiveProps is deprecated', - 'componentWillUpdate is deprecated', + 'componentWillMount has been renamed', + 'componentWillReceiveProps has been renamed', + 'componentWillUpdate has been renamed', ], {withoutStack: true}, ); @@ -604,9 +604,9 @@ describe('create-react-class-integration', () => { ); }).toLowPriorityWarnDev( [ - 'componentWillMount is deprecated', - 'componentWillReceiveProps is deprecated', - 'componentWillUpdate is deprecated', + 'componentWillMount has been renamed', + 'componentWillReceiveProps has been renamed', + 'componentWillUpdate has been renamed', ], {withoutStack: true}, ); @@ -649,9 +649,9 @@ describe('create-react-class-integration', () => { ReactDOM.render(, div), ).toLowPriorityWarnDev( [ - 'componentWillMount is deprecated', - 'componentWillReceiveProps is deprecated', - 'componentWillUpdate is deprecated', + 'componentWillMount has been renamed', + 'componentWillReceiveProps has been renamed', + 'componentWillUpdate has been renamed', ], {withoutStack: true}, ); diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.js index 1e1ec3610184..f71eb8275ed9 100644 --- a/packages/shared/forks/ReactFeatureFlags.test-renderer.js +++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.js @@ -15,7 +15,7 @@ import typeof * as PersistentFeatureFlagsType from './ReactFeatureFlags.persiste export const debugRenderPhaseSideEffects = false; export const debugRenderPhaseSideEffectsForStrictMode = false; export const enableUserTimingAPI = __DEV__; -export const warnAboutDeprecatedLifecycles = false; +export const warnAboutDeprecatedLifecycles = true; export const replayFailedUnitOfWorkWithInvokeGuardedCallback = false; export const enableProfilerTimer = false; export const enableSchedulerTracing = false; diff --git a/scripts/print-warnings/print-warnings.js b/scripts/print-warnings/print-warnings.js index db7630e9787f..cba05817d3e8 100644 --- a/scripts/print-warnings/print-warnings.js +++ b/scripts/print-warnings/print-warnings.js @@ -52,8 +52,17 @@ function transform(file, enc, cb) { // warning messages can be concatenated (`+`) at runtime, so here's // a trivial partial evaluator that interprets the literal value - const warningMsgLiteral = evalToString(node.arguments[1]); - warnings.add(JSON.stringify(warningMsgLiteral)); + try { + const warningMsgLiteral = evalToString(node.arguments[1]); + warnings.add(JSON.stringify(warningMsgLiteral)); + } catch (error) { + console.error( + 'Failed to extract warning message from', + file.path + ); + console.error(astPath.node.loc); + throw error; + } } }, },