@@ -194,6 +194,7 @@ const didWarnAboutModulePatternComponent = {};
194194const didWarnAboutDeprecatedWillMount = { } ;
195195const didWarnAboutUndefinedDerivedState = { } ;
196196const didWarnAboutUninitializedState = { } ;
197+ const didWarnAboutLegacyLifecyclesAndDerivedState = { } ;
197198const valuePropNames = [ 'value' , 'defaultValue' ] ;
198199const newlineEatingTags = {
199200 listing : true ,
@@ -475,6 +476,79 @@ function resolve(
475476 didWarnAboutUninitializedState [ componentName ] = true ;
476477 }
477478 }
479+
480+ // If new component APIs are defined, "unsafe" lifecycles won't be called.
481+ // Warn about these lifecycles if they are present.
482+ // Don't warn about react-lifecycles-compat polyfilled methods though.
483+ if (
484+ typeof Component . getDerivedStateFromProps === 'function' ||
485+ typeof inst . getSnapshotBeforeUpdate === 'function'
486+ ) {
487+ let foundWillMountName = null ;
488+ let foundWillReceivePropsName = null ;
489+ let foundWillUpdateName = null ;
490+ if (
491+ typeof inst . componentWillMount === 'function' &&
492+ inst . componentWillMount . __suppressDeprecationWarning !== true
493+ ) {
494+ foundWillMountName = 'componentWillMount ';
495+ } else if ( typeof inst . UNSAFE_componentWillMount === 'function' ) {
496+ foundWillMountName = 'UNSAFE_componentWillMount ';
497+ }
498+ if (
499+ typeof inst . componentWillReceiveProps === 'function' &&
500+ inst . componentWillReceiveProps . __suppressDeprecationWarning !==
501+ true
502+ ) {
503+ foundWillReceivePropsName = 'componentWillReceiveProps ';
504+ } else if (
505+ typeof inst . UNSAFE_componentWillReceiveProps === 'function'
506+ ) {
507+ foundWillReceivePropsName = 'UNSAFE_componentWillReceiveProps ';
508+ }
509+ if (
510+ typeof inst . componentWillUpdate === 'function' &&
511+ inst . componentWillUpdate . __suppressDeprecationWarning !== true
512+ ) {
513+ foundWillUpdateName = 'componentWillUpdate ';
514+ } else if ( typeof inst . UNSAFE_componentWillUpdate === 'function' ) {
515+ foundWillUpdateName = 'UNSAFE_componentWillUpdate ';
516+ }
517+ if (
518+ foundWillMountName !== null ||
519+ foundWillReceivePropsName !== null ||
520+ foundWillUpdateName !== null
521+ ) {
522+ const componentName =
523+ getComponentNameFromType ( Component ) || 'Component' ;
524+ const newApiName =
525+ typeof Component . getDerivedStateFromProps === 'function'
526+ ? 'getDerivedStateFromProps()'
527+ : 'getSnapshotBeforeUpdate()' ;
528+ if ( ! didWarnAboutLegacyLifecyclesAndDerivedState [ componentName ] ) {
529+ didWarnAboutLegacyLifecyclesAndDerivedState [
530+ componentName
531+ ] = true ;
532+ console . error (
533+ 'Unsafe legacy lifecycles will not be called for components using new component APIs.\n\n' +
534+ '%s uses %s but also contains the following legacy lifecycles:%s%s%s\n\n' +
535+ 'The above lifecycles should be removed. Learn more about this warning here:\n' +
536+ 'https://reactjs.org/link/unsafe-component-lifecycles' ,
537+ componentName ,
538+ newApiName ,
539+ foundWillMountName !== null
540+ ? `\n ${ foundWillMountName } `
541+ : '' ,
542+ foundWillReceivePropsName !== null
543+ ? `\n ${ foundWillReceivePropsName } `
544+ : '' ,
545+ foundWillUpdateName !== null
546+ ? `\n ${ foundWillUpdateName } `
547+ : '' ,
548+ ) ;
549+ }
550+ }
551+ }
478552 }
479553
480554 const partialState = Component . getDerivedStateFromProps . call (
@@ -575,32 +649,32 @@ function resolve(
575649 typeof inst . componentWillMount === 'function'
576650 ) {
577651 if ( typeof inst . componentWillMount === 'function' ) {
578- if ( __DEV__ ) {
579- if (
580- warnAboutDeprecatedLifecycles &&
581- inst . componentWillMount . __suppressDeprecationWarning !== true
582- ) {
583- const componentName =
584- getComponentNameFromType ( Component ) || 'Unknown' ;
585-
586- if ( ! didWarnAboutDeprecatedWillMount [ componentName ] ) {
587- console . warn (
588- // keep this warning in sync with ReactStrictModeWarning.js
589- 'componentWillMount has been renamed, and is not recommended for use. ' +
590- 'See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n' +
591- '* Move code from componentWillMount to componentDidMount (preferred in most cases) ' +
592- 'or the constructor.\n' +
593- '\nPlease update the following components: %s' ,
594- componentName ,
595- ) ;
596- didWarnAboutDeprecatedWillMount [ componentName ] = true ;
597- }
598- }
599- }
600-
601652 // In order to support react-lifecycles-compat polyfilled components,
602653 // Unsafe lifecycles should not be invoked for any component with the new gDSFP.
603654 if ( typeof Component . getDerivedStateFromProps !== 'function' ) {
655+ if ( __DEV__ ) {
656+ if (
657+ warnAboutDeprecatedLifecycles &&
658+ inst . componentWillMount . __suppressDeprecationWarning !== true
659+ ) {
660+ const componentName =
661+ getComponentNameFromType ( Component ) || 'Unknown' ;
662+
663+ if ( ! didWarnAboutDeprecatedWillMount [ componentName ] ) {
664+ console . warn (
665+ // keep this warning in sync with ReactStrictModeWarning.js
666+ 'componentWillMount has been renamed, and is not recommended for use. ' +
667+ 'See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n' +
668+ '* Move code from componentWillMount to componentDidMount (preferred in most cases) ' +
669+ 'or the constructor.\n' +
670+ '\nPlease update the following components: %s' ,
671+ componentName ,
672+ ) ;
673+ didWarnAboutDeprecatedWillMount [ componentName ] = true ;
674+ }
675+ }
676+ }
677+
604678 inst . componentWillMount ( ) ;
605679 }
606680 }
0 commit comments