@@ -841,6 +841,226 @@ describe('ReactHooks', () => {
841
841
) ;
842
842
} ) ;
843
843
844
+ it ( 'double-invokes components with Hooks in Strict Mode' , ( ) => {
845
+ ReactFeatureFlags . debugRenderPhaseSideEffectsForStrictMode = true ;
846
+
847
+ const { useState, StrictMode} = React ;
848
+ let renderCount = 0 ;
849
+
850
+ function NoHooks ( ) {
851
+ renderCount ++ ;
852
+ return < div /> ;
853
+ }
854
+
855
+ function HasHooks ( ) {
856
+ useState ( 0 ) ;
857
+ renderCount ++ ;
858
+ return < div /> ;
859
+ }
860
+
861
+ const FwdRef = React . forwardRef ( ( props , ref ) => {
862
+ renderCount ++ ;
863
+ return < div /> ;
864
+ } ) ;
865
+
866
+ const FwdRefHasHooks = React . forwardRef ( ( props , ref ) => {
867
+ useState ( 0 ) ;
868
+ renderCount ++ ;
869
+ return < div /> ;
870
+ } ) ;
871
+
872
+ const Memo = React . memo ( props => {
873
+ renderCount ++ ;
874
+ return < div /> ;
875
+ } ) ;
876
+
877
+ const MemoHasHooks = React . memo ( props => {
878
+ useState ( 0 ) ;
879
+ renderCount ++ ;
880
+ return < div /> ;
881
+ } ) ;
882
+
883
+ function Factory ( ) {
884
+ return {
885
+ state : { } ,
886
+ render ( ) {
887
+ renderCount ++ ;
888
+ return < div /> ;
889
+ } ,
890
+ } ;
891
+ }
892
+
893
+ let renderer = ReactTestRenderer . create ( null ) ;
894
+
895
+ renderCount = 0 ;
896
+ renderer . update ( < NoHooks /> ) ;
897
+ expect ( renderCount ) . toBe ( 1 ) ;
898
+ renderCount = 0 ;
899
+ renderer . update ( < NoHooks /> ) ;
900
+ expect ( renderCount ) . toBe ( 1 ) ;
901
+ renderCount = 0 ;
902
+ renderer . update (
903
+ < StrictMode >
904
+ < NoHooks />
905
+ </ StrictMode > ,
906
+ ) ;
907
+ expect ( renderCount ) . toBe ( 1 ) ;
908
+ renderCount = 0 ;
909
+ renderer . update (
910
+ < StrictMode >
911
+ < NoHooks />
912
+ </ StrictMode > ,
913
+ ) ;
914
+ expect ( renderCount ) . toBe ( 1 ) ;
915
+
916
+ renderCount = 0 ;
917
+ renderer . update ( < FwdRef /> ) ;
918
+ expect ( renderCount ) . toBe ( 1 ) ;
919
+ renderCount = 0 ;
920
+ renderer . update ( < FwdRef /> ) ;
921
+ expect ( renderCount ) . toBe ( 1 ) ;
922
+ renderCount = 0 ;
923
+ renderer . update (
924
+ < StrictMode >
925
+ < FwdRef />
926
+ </ StrictMode > ,
927
+ ) ;
928
+ expect ( renderCount ) . toBe ( 1 ) ;
929
+ renderCount = 0 ;
930
+ renderer . update (
931
+ < StrictMode >
932
+ < FwdRef />
933
+ </ StrictMode > ,
934
+ ) ;
935
+ expect ( renderCount ) . toBe ( 1 ) ;
936
+
937
+ renderCount = 0 ;
938
+ renderer . update ( < Memo arg = { 1 } /> ) ;
939
+ expect ( renderCount ) . toBe ( 1 ) ;
940
+ renderCount = 0 ;
941
+ renderer . update ( < Memo arg = { 2 } /> ) ;
942
+ expect ( renderCount ) . toBe ( 1 ) ;
943
+ renderCount = 0 ;
944
+ renderer . update (
945
+ < StrictMode >
946
+ < Memo arg = { 1 } />
947
+ </ StrictMode > ,
948
+ ) ;
949
+ expect ( renderCount ) . toBe ( 1 ) ;
950
+ renderCount = 0 ;
951
+ renderer . update (
952
+ < StrictMode >
953
+ < Memo arg = { 2 } />
954
+ </ StrictMode > ,
955
+ ) ;
956
+ expect ( renderCount ) . toBe ( 1 ) ;
957
+
958
+ renderCount = 0 ;
959
+ renderer . update ( < Factory /> ) ;
960
+ expect ( renderCount ) . toBe ( 1 ) ;
961
+ renderCount = 0 ;
962
+ renderer . update ( < Factory /> ) ;
963
+ expect ( renderCount ) . toBe ( 1 ) ;
964
+ renderCount = 0 ;
965
+ renderer . update (
966
+ < StrictMode >
967
+ < Factory />
968
+ </ StrictMode > ,
969
+ ) ;
970
+ expect ( renderCount ) . toBe ( __DEV__ ? 2 : 1 ) ; // Treated like a class
971
+ renderCount = 0 ;
972
+ renderer . update (
973
+ < StrictMode >
974
+ < Factory />
975
+ </ StrictMode > ,
976
+ ) ;
977
+ expect ( renderCount ) . toBe ( __DEV__ ? 2 : 1 ) ; // Treated like a class
978
+
979
+ renderCount = 0 ;
980
+ renderer . update ( < HasHooks /> ) ;
981
+ expect ( renderCount ) . toBe ( 1 ) ;
982
+ renderCount = 0 ;
983
+ renderer . update ( < HasHooks /> ) ;
984
+ expect ( renderCount ) . toBe ( 1 ) ;
985
+ renderCount = 0 ;
986
+ renderer . update (
987
+ < StrictMode >
988
+ < HasHooks />
989
+ </ StrictMode > ,
990
+ ) ;
991
+ expect ( renderCount ) . toBe ( __DEV__ ? 2 : 1 ) ; // Has Hooks
992
+ renderCount = 0 ;
993
+ renderer . update (
994
+ < StrictMode >
995
+ < HasHooks />
996
+ </ StrictMode > ,
997
+ ) ;
998
+ expect ( renderCount ) . toBe ( __DEV__ ? 2 : 1 ) ; // Has Hooks
999
+
1000
+ renderCount = 0 ;
1001
+ renderer . update ( < FwdRefHasHooks /> ) ;
1002
+ expect ( renderCount ) . toBe ( 1 ) ;
1003
+ renderCount = 0 ;
1004
+ renderer . update ( < FwdRefHasHooks /> ) ;
1005
+ expect ( renderCount ) . toBe ( 1 ) ;
1006
+ renderCount = 0 ;
1007
+ renderer . update (
1008
+ < StrictMode >
1009
+ < FwdRefHasHooks />
1010
+ </ StrictMode > ,
1011
+ ) ;
1012
+ expect ( renderCount ) . toBe ( __DEV__ ? 2 : 1 ) ; // Has Hooks
1013
+ renderCount = 0 ;
1014
+ renderer . update (
1015
+ < StrictMode >
1016
+ < FwdRefHasHooks />
1017
+ </ StrictMode > ,
1018
+ ) ;
1019
+ expect ( renderCount ) . toBe ( __DEV__ ? 2 : 1 ) ; // Has Hooks
1020
+
1021
+ renderCount = 0 ;
1022
+ renderer . update ( < MemoHasHooks arg = { 1 } /> ) ;
1023
+ expect ( renderCount ) . toBe ( 1 ) ;
1024
+ renderCount = 0 ;
1025
+ renderer . update ( < MemoHasHooks arg = { 2 } /> ) ;
1026
+ expect ( renderCount ) . toBe ( 1 ) ;
1027
+ renderCount = 0 ;
1028
+ renderer . update (
1029
+ < StrictMode >
1030
+ < MemoHasHooks arg = { 1 } />
1031
+ </ StrictMode > ,
1032
+ ) ;
1033
+ expect ( renderCount ) . toBe ( __DEV__ ? 2 : 1 ) ; // Has Hooks
1034
+ renderCount = 0 ;
1035
+ renderer . update (
1036
+ < StrictMode >
1037
+ < MemoHasHooks arg = { 2 } />
1038
+ </ StrictMode > ,
1039
+ ) ;
1040
+ expect ( renderCount ) . toBe ( __DEV__ ? 2 : 1 ) ; // Has Hooks
1041
+ } ) ;
1042
+
1043
+ it ( 'double-invokes useMemo in DEV StrictMode despite []' , ( ) => {
1044
+ ReactFeatureFlags . debugRenderPhaseSideEffectsForStrictMode = true ;
1045
+ const { useMemo, StrictMode} = React ;
1046
+
1047
+ let useMemoCount = 0 ;
1048
+ function BadUseMemo ( ) {
1049
+ useMemo ( ( ) => {
1050
+ useMemoCount ++ ;
1051
+ } , [ ] ) ;
1052
+ return < div /> ;
1053
+ }
1054
+
1055
+ useMemoCount = 0 ;
1056
+ ReactTestRenderer . create (
1057
+ < StrictMode >
1058
+ < BadUseMemo />
1059
+ </ StrictMode > ,
1060
+ ) ;
1061
+ expect ( useMemoCount ) . toBe ( __DEV__ ? 2 : 1 ) ; // Has Hooks
1062
+ } ) ;
1063
+
844
1064
it ( 'warns on using differently ordered hooks on subsequent renders' , ( ) => {
845
1065
const { useState, useReducer} = React ;
846
1066
function useCustomHook ( ) {
0 commit comments