@@ -65,6 +65,8 @@ let didWarnAboutUndefinedDerivedState;
6565let warnOnUndefinedDerivedState ;
6666let warnOnInvalidCallback ;
6767let didWarnAboutDirectlyAssigningPropsToState ;
68+ let didWarnAboutContextTypeAndContextTypes ;
69+ let didWarnAboutInvalidateContextType ;
6870
6971if ( __DEV__ ) {
7072 didWarnAboutStateAssignmentForComponent = new Set ( ) ;
@@ -73,6 +75,8 @@ if (__DEV__) {
7375 didWarnAboutLegacyLifecyclesAndDerivedState = new Set ( ) ;
7476 didWarnAboutDirectlyAssigningPropsToState = new Set ( ) ;
7577 didWarnAboutUndefinedDerivedState = new Set ( ) ;
78+ didWarnAboutContextTypeAndContextTypes = new Set ( ) ;
79+ didWarnAboutInvalidateContextType = new Set ( ) ;
7680
7781 const didWarnOnInvalidCallback = new Set ( ) ;
7882
@@ -234,15 +238,15 @@ function checkShouldComponentUpdate(
234238 newProps ,
235239 oldState ,
236240 newState ,
237- nextLegacyContext ,
241+ nextContext ,
238242) {
239243 const instance = workInProgress . stateNode ;
240244 if ( typeof instance . shouldComponentUpdate === 'function' ) {
241245 startPhaseTimer ( workInProgress , 'shouldComponentUpdate' ) ;
242246 const shouldUpdate = instance . shouldComponentUpdate (
243247 newProps ,
244248 newState ,
245- nextLegacyContext ,
249+ nextContext ,
246250 ) ;
247251 stopPhaseTimer ( ) ;
248252
@@ -319,13 +323,50 @@ function checkClassInstance(workInProgress: Fiber, ctor: any, newProps: any) {
319323 'property to define propTypes instead.' ,
320324 name ,
321325 ) ;
326+ const noInstanceContextType = ! instance . contextType ;
327+ warningWithoutStack (
328+ noInstanceContextType ,
329+ 'contextType was defined as an instance property on %s. Use a static ' +
330+ 'property to define contextType instead.' ,
331+ name ,
332+ ) ;
322333 const noInstanceContextTypes = ! instance . contextTypes ;
323334 warningWithoutStack (
324335 noInstanceContextTypes ,
325336 'contextTypes was defined as an instance property on %s. Use a static ' +
326337 'property to define contextTypes instead.' ,
327338 name ,
328339 ) ;
340+
341+ if (
342+ ctor . contextType &&
343+ ctor . contextTypes &&
344+ ! didWarnAboutContextTypeAndContextTypes . has ( ctor )
345+ ) {
346+ didWarnAboutContextTypeAndContextTypes . add ( ctor ) ;
347+ warningWithoutStack (
348+ false ,
349+ '%s declares both contextTypes and contextType static properties. ' +
350+ 'The legacy contextTypes property will be ignored.' ,
351+ name ,
352+ ) ;
353+ }
354+
355+ if (
356+ ctor . contextType &&
357+ typeof ctor . contextType . unstable_read !== 'function' &&
358+ ! didWarnAboutInvalidateContextType . has ( ctor )
359+ ) {
360+ didWarnAboutInvalidateContextType . add ( ctor ) ;
361+ warningWithoutStack (
362+ false ,
363+ '%s defines an invalid contextType. ' +
364+ 'contextType should point to the Context object returned by React.createContext(). ' +
365+ 'Did you accidentally pass the Context.Provider instead?' ,
366+ name ,
367+ ) ;
368+ }
369+
329370 const noComponentShouldUpdate =
330371 typeof instance . componentShouldUpdate !== 'function' ;
331372 warningWithoutStack (
@@ -475,12 +516,25 @@ function constructClassInstance(
475516 props : any ,
476517 renderExpirationTime : ExpirationTime ,
477518) : any {
478- const unmaskedContext = getUnmaskedContext ( workInProgress , ctor , true ) ;
479- const contextTypes = ctor . contextTypes ;
480- const isContextConsumer = contextTypes !== null && contextTypes !== undefined ;
481- const context = isContextConsumer
482- ? getMaskedContext ( workInProgress , unmaskedContext )
483- : emptyContextObject ;
519+ let isLegacyContextConsumer = false ;
520+ let unmaskedContext = emptyContextObject ;
521+ let context = null ;
522+ const contextType = ctor . contextType ;
523+ if (
524+ typeof contextType === 'object' &&
525+ contextType !== null &&
526+ typeof contextType . unstable_read === 'function'
527+ ) {
528+ context = ( contextType : any ) . unstable_read ( ) ;
529+ } else {
530+ unmaskedContext = getUnmaskedContext ( workInProgress , ctor , true ) ;
531+ const contextTypes = ctor . contextTypes ;
532+ isLegacyContextConsumer =
533+ contextTypes !== null && contextTypes !== undefined ;
534+ context = isLegacyContextConsumer
535+ ? getMaskedContext ( workInProgress , unmaskedContext )
536+ : emptyContextObject ;
537+ }
484538
485539 // Instantiate twice to help detect side-effects.
486540 if ( __DEV__ ) {
@@ -587,7 +641,7 @@ function constructClassInstance(
587641
588642 // Cache unmasked context so we can avoid recreating masked context unless necessary.
589643 // ReactFiberContext usually updates this cache but can't for newly-created instances.
590- if ( isContextConsumer ) {
644+ if ( isLegacyContextConsumer ) {
591645 cacheContext ( workInProgress , unmaskedContext , context ) ;
592646 }
593647
@@ -625,15 +679,15 @@ function callComponentWillReceiveProps(
625679 workInProgress ,
626680 instance ,
627681 newProps ,
628- nextLegacyContext ,
682+ nextContext ,
629683) {
630684 const oldState = instance . state ;
631685 startPhaseTimer ( workInProgress , 'componentWillReceiveProps' ) ;
632686 if ( typeof instance . componentWillReceiveProps === 'function' ) {
633- instance . componentWillReceiveProps ( newProps , nextLegacyContext ) ;
687+ instance . componentWillReceiveProps ( newProps , nextContext ) ;
634688 }
635689 if ( typeof instance . UNSAFE_componentWillReceiveProps === 'function' ) {
636- instance . UNSAFE_componentWillReceiveProps ( newProps , nextLegacyContext ) ;
690+ instance . UNSAFE_componentWillReceiveProps ( newProps , nextContext ) ;
637691 }
638692 stopPhaseTimer ( ) ;
639693
@@ -668,12 +722,21 @@ function mountClassInstance(
668722 }
669723
670724 const instance = workInProgress . stateNode ;
671- const unmaskedContext = getUnmaskedContext ( workInProgress , ctor , true ) ;
672-
673725 instance . props = newProps ;
674726 instance . state = workInProgress . memoizedState ;
675727 instance . refs = emptyRefsObject ;
676- instance . context = getMaskedContext ( workInProgress , unmaskedContext ) ;
728+
729+ const contextType = ctor . contextType ;
730+ if (
731+ typeof contextType === 'object' &&
732+ contextType !== null &&
733+ typeof contextType . unstable_read === 'function'
734+ ) {
735+ instance . context = ( contextType : any ) . unstable_read ( ) ;
736+ } else {
737+ const unmaskedContext = getUnmaskedContext ( workInProgress , ctor , true ) ;
738+ instance . context = getMaskedContext ( workInProgress , unmaskedContext ) ;
739+ }
677740
678741 if ( __DEV__ ) {
679742 if ( instance . state === newProps ) {
@@ -774,15 +837,22 @@ function resumeMountClassInstance(
774837 instance . props = oldProps ;
775838
776839 const oldContext = instance . context ;
777- const nextLegacyUnmaskedContext = getUnmaskedContext (
778- workInProgress ,
779- ctor ,
780- true ,
781- ) ;
782- const nextLegacyContext = getMaskedContext (
783- workInProgress ,
784- nextLegacyUnmaskedContext ,
785- ) ;
840+ const contextType = ctor . contextType ;
841+ let nextContext ;
842+ if (
843+ typeof contextType === 'object' &&
844+ contextType !== null &&
845+ typeof contextType . unstable_read === 'function'
846+ ) {
847+ nextContext = ( contextType : any ) . unstable_read ( ) ;
848+ } else {
849+ const nextLegacyUnmaskedContext = getUnmaskedContext (
850+ workInProgress ,
851+ ctor ,
852+ true ,
853+ ) ;
854+ nextContext = getMaskedContext ( workInProgress , nextLegacyUnmaskedContext ) ;
855+ }
786856
787857 const getDerivedStateFromProps = ctor . getDerivedStateFromProps ;
788858 const hasNewLifecycles =
@@ -800,12 +870,12 @@ function resumeMountClassInstance(
800870 ( typeof instance . UNSAFE_componentWillReceiveProps === 'function' ||
801871 typeof instance . componentWillReceiveProps === 'function' )
802872 ) {
803- if ( oldProps !== newProps || oldContext !== nextLegacyContext ) {
873+ if ( oldProps !== newProps || oldContext !== nextContext ) {
804874 callComponentWillReceiveProps (
805875 workInProgress ,
806876 instance ,
807877 newProps ,
808- nextLegacyContext ,
878+ nextContext ,
809879 ) ;
810880 }
811881 }
@@ -858,7 +928,7 @@ function resumeMountClassInstance(
858928 newProps ,
859929 oldState ,
860930 newState ,
861- nextLegacyContext ,
931+ nextContext ,
862932 ) ;
863933
864934 if ( shouldUpdate ) {
@@ -898,7 +968,7 @@ function resumeMountClassInstance(
898968 // if shouldComponentUpdate returns false.
899969 instance . props = newProps ;
900970 instance . state = newState ;
901- instance . context = nextLegacyContext ;
971+ instance . context = nextContext ;
902972
903973 return shouldUpdate ;
904974}
@@ -917,15 +987,18 @@ function updateClassInstance(
917987 instance . props = oldProps ;
918988
919989 const oldContext = instance . context ;
920- const nextLegacyUnmaskedContext = getUnmaskedContext (
921- workInProgress ,
922- ctor ,
923- true ,
924- ) ;
925- const nextLegacyContext = getMaskedContext (
926- workInProgress ,
927- nextLegacyUnmaskedContext ,
928- ) ;
990+ const contextType = ctor . contextType ;
991+ let nextContext ;
992+ if (
993+ typeof contextType === 'object' &&
994+ contextType !== null &&
995+ typeof contextType . unstable_read === 'function'
996+ ) {
997+ nextContext = ( contextType : any ) . unstable_read ( ) ;
998+ } else {
999+ const nextUnmaskedContext = getUnmaskedContext ( workInProgress , ctor , true ) ;
1000+ nextContext = getMaskedContext ( workInProgress , nextUnmaskedContext ) ;
1001+ }
9291002
9301003 const getDerivedStateFromProps = ctor . getDerivedStateFromProps ;
9311004 const hasNewLifecycles =
@@ -943,12 +1016,12 @@ function updateClassInstance(
9431016 ( typeof instance . UNSAFE_componentWillReceiveProps === 'function' ||
9441017 typeof instance . componentWillReceiveProps === 'function' )
9451018 ) {
946- if ( oldProps !== newProps || oldContext !== nextLegacyContext ) {
1019+ if ( oldProps !== newProps || oldContext !== nextContext ) {
9471020 callComponentWillReceiveProps (
9481021 workInProgress ,
9491022 instance ,
9501023 newProps ,
951- nextLegacyContext ,
1024+ nextContext ,
9521025 ) ;
9531026 }
9541027 }
@@ -1015,7 +1088,7 @@ function updateClassInstance(
10151088 newProps ,
10161089 oldState ,
10171090 newState ,
1018- nextLegacyContext ,
1091+ nextContext ,
10191092 ) ;
10201093
10211094 if ( shouldUpdate ) {
@@ -1028,14 +1101,10 @@ function updateClassInstance(
10281101 ) {
10291102 startPhaseTimer ( workInProgress , 'componentWillUpdate' ) ;
10301103 if ( typeof instance . componentWillUpdate === 'function' ) {
1031- instance . componentWillUpdate ( newProps , newState , nextLegacyContext ) ;
1104+ instance . componentWillUpdate ( newProps , newState , nextContext ) ;
10321105 }
10331106 if ( typeof instance . UNSAFE_componentWillUpdate === 'function' ) {
1034- instance . UNSAFE_componentWillUpdate (
1035- newProps ,
1036- newState ,
1037- nextLegacyContext ,
1038- ) ;
1107+ instance . UNSAFE_componentWillUpdate ( newProps , newState , nextContext ) ;
10391108 }
10401109 stopPhaseTimer ( ) ;
10411110 }
@@ -1075,7 +1144,7 @@ function updateClassInstance(
10751144 // if shouldComponentUpdate returns false.
10761145 instance . props = newProps ;
10771146 instance . state = newState ;
1078- instance . context = nextLegacyContext ;
1147+ instance . context = nextContext ;
10791148
10801149 return shouldUpdate ;
10811150}
0 commit comments