@@ -65,6 +65,8 @@ let didWarnAboutUndefinedDerivedState;
65
65
let warnOnUndefinedDerivedState ;
66
66
let warnOnInvalidCallback ;
67
67
let didWarnAboutDirectlyAssigningPropsToState ;
68
+ let didWarnAboutContextTypeAndContextTypes ;
69
+ let didWarnAboutInvalidateContextType ;
68
70
69
71
if ( __DEV__ ) {
70
72
didWarnAboutStateAssignmentForComponent = new Set ( ) ;
@@ -73,6 +75,8 @@ if (__DEV__) {
73
75
didWarnAboutLegacyLifecyclesAndDerivedState = new Set ( ) ;
74
76
didWarnAboutDirectlyAssigningPropsToState = new Set ( ) ;
75
77
didWarnAboutUndefinedDerivedState = new Set ( ) ;
78
+ didWarnAboutContextTypeAndContextTypes = new Set ( ) ;
79
+ didWarnAboutInvalidateContextType = new Set ( ) ;
76
80
77
81
const didWarnOnInvalidCallback = new Set ( ) ;
78
82
@@ -234,15 +238,15 @@ function checkShouldComponentUpdate(
234
238
newProps ,
235
239
oldState ,
236
240
newState ,
237
- nextLegacyContext ,
241
+ nextContext ,
238
242
) {
239
243
const instance = workInProgress . stateNode ;
240
244
if ( typeof instance . shouldComponentUpdate === 'function' ) {
241
245
startPhaseTimer ( workInProgress , 'shouldComponentUpdate' ) ;
242
246
const shouldUpdate = instance . shouldComponentUpdate (
243
247
newProps ,
244
248
newState ,
245
- nextLegacyContext ,
249
+ nextContext ,
246
250
) ;
247
251
stopPhaseTimer ( ) ;
248
252
@@ -319,13 +323,50 @@ function checkClassInstance(workInProgress: Fiber, ctor: any, newProps: any) {
319
323
'property to define propTypes instead.' ,
320
324
name ,
321
325
) ;
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
+ ) ;
322
333
const noInstanceContextTypes = ! instance . contextTypes ;
323
334
warningWithoutStack (
324
335
noInstanceContextTypes ,
325
336
'contextTypes was defined as an instance property on %s. Use a static ' +
326
337
'property to define contextTypes instead.' ,
327
338
name ,
328
339
) ;
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
+
329
370
const noComponentShouldUpdate =
330
371
typeof instance . componentShouldUpdate !== 'function' ;
331
372
warningWithoutStack (
@@ -475,12 +516,25 @@ function constructClassInstance(
475
516
props : any ,
476
517
renderExpirationTime : ExpirationTime ,
477
518
) : 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
+ }
484
538
485
539
// Instantiate twice to help detect side-effects.
486
540
if ( __DEV__ ) {
@@ -587,7 +641,7 @@ function constructClassInstance(
587
641
588
642
// Cache unmasked context so we can avoid recreating masked context unless necessary.
589
643
// ReactFiberContext usually updates this cache but can't for newly-created instances.
590
- if ( isContextConsumer ) {
644
+ if ( isLegacyContextConsumer ) {
591
645
cacheContext ( workInProgress , unmaskedContext , context ) ;
592
646
}
593
647
@@ -625,15 +679,15 @@ function callComponentWillReceiveProps(
625
679
workInProgress ,
626
680
instance ,
627
681
newProps ,
628
- nextLegacyContext ,
682
+ nextContext ,
629
683
) {
630
684
const oldState = instance . state ;
631
685
startPhaseTimer ( workInProgress , 'componentWillReceiveProps' ) ;
632
686
if ( typeof instance . componentWillReceiveProps === 'function' ) {
633
- instance . componentWillReceiveProps ( newProps , nextLegacyContext ) ;
687
+ instance . componentWillReceiveProps ( newProps , nextContext ) ;
634
688
}
635
689
if ( typeof instance . UNSAFE_componentWillReceiveProps === 'function' ) {
636
- instance . UNSAFE_componentWillReceiveProps ( newProps , nextLegacyContext ) ;
690
+ instance . UNSAFE_componentWillReceiveProps ( newProps , nextContext ) ;
637
691
}
638
692
stopPhaseTimer ( ) ;
639
693
@@ -668,12 +722,21 @@ function mountClassInstance(
668
722
}
669
723
670
724
const instance = workInProgress . stateNode ;
671
- const unmaskedContext = getUnmaskedContext ( workInProgress , ctor , true ) ;
672
-
673
725
instance . props = newProps ;
674
726
instance . state = workInProgress . memoizedState ;
675
727
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
+ }
677
740
678
741
if ( __DEV__ ) {
679
742
if ( instance . state === newProps ) {
@@ -774,15 +837,22 @@ function resumeMountClassInstance(
774
837
instance . props = oldProps ;
775
838
776
839
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
+ }
786
856
787
857
const getDerivedStateFromProps = ctor . getDerivedStateFromProps ;
788
858
const hasNewLifecycles =
@@ -800,12 +870,12 @@ function resumeMountClassInstance(
800
870
( typeof instance . UNSAFE_componentWillReceiveProps === 'function' ||
801
871
typeof instance . componentWillReceiveProps === 'function' )
802
872
) {
803
- if ( oldProps !== newProps || oldContext !== nextLegacyContext ) {
873
+ if ( oldProps !== newProps || oldContext !== nextContext ) {
804
874
callComponentWillReceiveProps (
805
875
workInProgress ,
806
876
instance ,
807
877
newProps ,
808
- nextLegacyContext ,
878
+ nextContext ,
809
879
) ;
810
880
}
811
881
}
@@ -858,7 +928,7 @@ function resumeMountClassInstance(
858
928
newProps ,
859
929
oldState ,
860
930
newState ,
861
- nextLegacyContext ,
931
+ nextContext ,
862
932
) ;
863
933
864
934
if ( shouldUpdate ) {
@@ -898,7 +968,7 @@ function resumeMountClassInstance(
898
968
// if shouldComponentUpdate returns false.
899
969
instance . props = newProps ;
900
970
instance . state = newState ;
901
- instance . context = nextLegacyContext ;
971
+ instance . context = nextContext ;
902
972
903
973
return shouldUpdate ;
904
974
}
@@ -917,15 +987,18 @@ function updateClassInstance(
917
987
instance . props = oldProps ;
918
988
919
989
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
+ }
929
1002
930
1003
const getDerivedStateFromProps = ctor . getDerivedStateFromProps ;
931
1004
const hasNewLifecycles =
@@ -943,12 +1016,12 @@ function updateClassInstance(
943
1016
( typeof instance . UNSAFE_componentWillReceiveProps === 'function' ||
944
1017
typeof instance . componentWillReceiveProps === 'function' )
945
1018
) {
946
- if ( oldProps !== newProps || oldContext !== nextLegacyContext ) {
1019
+ if ( oldProps !== newProps || oldContext !== nextContext ) {
947
1020
callComponentWillReceiveProps (
948
1021
workInProgress ,
949
1022
instance ,
950
1023
newProps ,
951
- nextLegacyContext ,
1024
+ nextContext ,
952
1025
) ;
953
1026
}
954
1027
}
@@ -1015,7 +1088,7 @@ function updateClassInstance(
1015
1088
newProps ,
1016
1089
oldState ,
1017
1090
newState ,
1018
- nextLegacyContext ,
1091
+ nextContext ,
1019
1092
) ;
1020
1093
1021
1094
if ( shouldUpdate ) {
@@ -1028,14 +1101,10 @@ function updateClassInstance(
1028
1101
) {
1029
1102
startPhaseTimer ( workInProgress , 'componentWillUpdate' ) ;
1030
1103
if ( typeof instance . componentWillUpdate === 'function' ) {
1031
- instance . componentWillUpdate ( newProps , newState , nextLegacyContext ) ;
1104
+ instance . componentWillUpdate ( newProps , newState , nextContext ) ;
1032
1105
}
1033
1106
if ( typeof instance . UNSAFE_componentWillUpdate === 'function' ) {
1034
- instance . UNSAFE_componentWillUpdate (
1035
- newProps ,
1036
- newState ,
1037
- nextLegacyContext ,
1038
- ) ;
1107
+ instance . UNSAFE_componentWillUpdate ( newProps , newState , nextContext ) ;
1039
1108
}
1040
1109
stopPhaseTimer ( ) ;
1041
1110
}
@@ -1075,7 +1144,7 @@ function updateClassInstance(
1075
1144
// if shouldComponentUpdate returns false.
1076
1145
instance . props = newProps ;
1077
1146
instance . state = newState ;
1078
- instance . context = nextLegacyContext ;
1147
+ instance . context = nextContext ;
1079
1148
1080
1149
return shouldUpdate ;
1081
1150
}
0 commit comments