@@ -2632,6 +2632,54 @@ describe('ReactHooksWithNoopRenderer', () => {
2632
2632
} ) ;
2633
2633
expect ( Scheduler ) . toHaveYielded ( [ 'layout destroy' , 'passive destroy' ] ) ;
2634
2634
} ) ;
2635
+
2636
+ it ( 'assumes passive effect destroy function is either a function or undefined' , ( ) => {
2637
+ function App ( props ) {
2638
+ useEffect ( ( ) => {
2639
+ return props . return ;
2640
+ } ) ;
2641
+ return null ;
2642
+ }
2643
+
2644
+ const root1 = ReactNoop . createRoot ( ) ;
2645
+ expect ( ( ) =>
2646
+ act ( ( ) => {
2647
+ root1 . render ( < App return = { 17 } /> ) ;
2648
+ } ) ,
2649
+ ) . toErrorDev ( [
2650
+ 'Warning: An effect function must not return anything besides a ' +
2651
+ 'function, which is used for clean-up. You returned: 17' ,
2652
+ ] ) ;
2653
+
2654
+ const root2 = ReactNoop . createRoot ( ) ;
2655
+ expect ( ( ) =>
2656
+ act ( ( ) => {
2657
+ root2 . render ( < App return = { null } /> ) ;
2658
+ } ) ,
2659
+ ) . toErrorDev ( [
2660
+ 'Warning: An effect function must not return anything besides a ' +
2661
+ 'function, which is used for clean-up. You returned null. If your ' +
2662
+ 'effect does not require clean up, return undefined (or nothing).' ,
2663
+ ] ) ;
2664
+
2665
+ const root3 = ReactNoop . createRoot ( ) ;
2666
+ expect ( ( ) =>
2667
+ act ( ( ) => {
2668
+ root3 . render ( < App return = { Promise . resolve ( ) } /> ) ;
2669
+ } ) ,
2670
+ ) . toErrorDev ( [
2671
+ 'Warning: An effect function must not return anything besides a ' +
2672
+ 'function, which is used for clean-up.\n\n' +
2673
+ 'It looks like you wrote useEffect(async () => ...) or returned a Promise.' ,
2674
+ ] ) ;
2675
+
2676
+ // Error on unmount because React assumes the value is a function
2677
+ expect ( ( ) =>
2678
+ act ( ( ) => {
2679
+ root3 . unmount ( ) ;
2680
+ } ) ,
2681
+ ) . toThrow ( 'is not a function' ) ;
2682
+ } ) ;
2635
2683
} ) ;
2636
2684
2637
2685
describe ( 'useLayoutEffect' , ( ) => {
@@ -2810,6 +2858,54 @@ describe('ReactHooksWithNoopRenderer', () => {
2810
2858
] ) ;
2811
2859
expect ( ReactNoop . getChildren ( ) ) . toEqual ( [ span ( 'OuterFallback' ) ] ) ;
2812
2860
} ) ;
2861
+
2862
+ it ( 'assumes layout effect destroy function is either a function or undefined' , ( ) => {
2863
+ function App ( props ) {
2864
+ useLayoutEffect ( ( ) => {
2865
+ return props . return ;
2866
+ } ) ;
2867
+ return null ;
2868
+ }
2869
+
2870
+ const root1 = ReactNoop . createRoot ( ) ;
2871
+ expect ( ( ) =>
2872
+ act ( ( ) => {
2873
+ root1 . render ( < App return = { 17 } /> ) ;
2874
+ } ) ,
2875
+ ) . toErrorDev ( [
2876
+ 'Warning: An effect function must not return anything besides a ' +
2877
+ 'function, which is used for clean-up. You returned: 17' ,
2878
+ ] ) ;
2879
+
2880
+ const root2 = ReactNoop . createRoot ( ) ;
2881
+ expect ( ( ) =>
2882
+ act ( ( ) => {
2883
+ root2 . render ( < App return = { null } /> ) ;
2884
+ } ) ,
2885
+ ) . toErrorDev ( [
2886
+ 'Warning: An effect function must not return anything besides a ' +
2887
+ 'function, which is used for clean-up. You returned null. If your ' +
2888
+ 'effect does not require clean up, return undefined (or nothing).' ,
2889
+ ] ) ;
2890
+
2891
+ const root3 = ReactNoop . createRoot ( ) ;
2892
+ expect ( ( ) =>
2893
+ act ( ( ) => {
2894
+ root3 . render ( < App return = { Promise . resolve ( ) } /> ) ;
2895
+ } ) ,
2896
+ ) . toErrorDev ( [
2897
+ 'Warning: An effect function must not return anything besides a ' +
2898
+ 'function, which is used for clean-up.\n\n' +
2899
+ 'It looks like you wrote useEffect(async () => ...) or returned a Promise.' ,
2900
+ ] ) ;
2901
+
2902
+ // Error on unmount because React assumes the value is a function
2903
+ expect ( ( ) =>
2904
+ act ( ( ) => {
2905
+ root3 . unmount ( ) ;
2906
+ } ) ,
2907
+ ) . toThrow ( 'is not a function' ) ;
2908
+ } ) ;
2813
2909
} ) ;
2814
2910
2815
2911
describe ( 'useCallback' , ( ) => {
0 commit comments