@@ -26,7 +26,7 @@ main() {
26
26
ButtonElement setWithUpdaterButtonRef;
27
27
28
28
setUpAll (() {
29
- var mountNode = new DivElement ();
29
+ var mountNode = DivElement ();
30
30
31
31
UseStateTest = react.registerFunctionComponent ((Map props) {
32
32
final text = useStateLazy (() {
@@ -105,7 +105,7 @@ main() {
105
105
int useEffectCleanupWithEmptyDepsCallCount;
106
106
107
107
setUpAll (() {
108
- mountNode = new DivElement ();
108
+ mountNode = DivElement ();
109
109
useEffectCallCount = 0 ;
110
110
useEffectCleanupCallCount = 0 ;
111
111
useEffectWithDepsCallCount = 0 ;
@@ -268,7 +268,7 @@ main() {
268
268
}
269
269
270
270
setUpAll (() {
271
- var mountNode = new DivElement ();
271
+ var mountNode = DivElement ();
272
272
273
273
UseReducerTest = react.registerFunctionComponent ((Map props) {
274
274
final state = useReducer (reducer, {
@@ -362,7 +362,7 @@ main() {
362
362
}
363
363
364
364
setUpAll (() {
365
- var mountNode = new DivElement ();
365
+ var mountNode = DivElement ();
366
366
367
367
UseReducerTest = react.registerFunctionComponent ((Map props) {
368
368
final ReducerHook <Map , Map , int > state = useReducerLazy (reducer2, props['initialCount' ], initializeCount);
@@ -435,7 +435,7 @@ main() {
435
435
ButtonElement incrementDeltaButtonRef;
436
436
437
437
setUpAll (() {
438
- var mountNode = new DivElement ();
438
+ var mountNode = DivElement ();
439
439
440
440
UseCallbackTest = react.registerFunctionComponent ((Map props) {
441
441
final count = useState (0 );
@@ -519,7 +519,7 @@ main() {
519
519
expect (countRef.text, '3' , reason: 'still increments by 1 because delta not in dependency list' );
520
520
});
521
521
522
- test ('callback stays the same if state not in dependency list' , () {
522
+ test ('callback updates if state is in dependency list' , () {
523
523
react_test_utils.Simulate .click (incrementWithDepButtonRef);
524
524
expect (countRef.text, '5' , reason: 'increments by 2 because delta updated' );
525
525
});
@@ -589,7 +589,7 @@ main() {
589
589
});
590
590
591
591
group ('useRef -' , () {
592
- var mountNode = new DivElement ();
592
+ var mountNode = DivElement ();
593
593
ReactDartFunctionComponentFactoryProxy UseRefTest ;
594
594
ButtonElement reRenderButton;
595
595
var noInitRef;
@@ -666,6 +666,130 @@ main() {
666
666
});
667
667
});
668
668
});
669
+
670
+ group ('useMemo -' , () {
671
+ ReactDartFunctionComponentFactoryProxy UseMemoTest ;
672
+ StateHook <int > count;
673
+ ButtonElement reRenderButtonRef;
674
+ ButtonElement incrementButtonRef;
675
+
676
+ // Count how many times createFunction() is called for each variation of dependencies.
677
+ int createFunctionCallCountWithDeps = 0 ;
678
+ int createFunctionCallCountNoDeps = 0 ;
679
+ int createFunctionCallCountEmptyDeps = 0 ;
680
+
681
+ // Keeps track of return value of useMemo() for each variation of dependencies.
682
+ int returnValueWithDeps;
683
+ int returnValueNoDeps;
684
+ int returnValueEmptyDeps;
685
+
686
+ int fibonacci (int n) {
687
+ if (n <= 1 ) {
688
+ return 1 ;
689
+ }
690
+ return fibonacci (n - 1 ) + fibonacci (n - 2 );
691
+ }
692
+
693
+ setUpAll (() {
694
+ final mountNode = DivElement ();
695
+
696
+ UseMemoTest = react.registerFunctionComponent ((Map props) {
697
+ final reRender = useState (0 );
698
+ count = useState (5 );
699
+
700
+ returnValueWithDeps = useMemo (
701
+ () {
702
+ createFunctionCallCountWithDeps++ ;
703
+ return fibonacci (count.value);
704
+ },
705
+ [count.value],
706
+ );
707
+
708
+ returnValueNoDeps = useMemo (
709
+ () {
710
+ createFunctionCallCountNoDeps++ ;
711
+ return fibonacci (count.value);
712
+ },
713
+ );
714
+
715
+ returnValueEmptyDeps = useMemo (
716
+ () {
717
+ createFunctionCallCountEmptyDeps++ ;
718
+ return fibonacci (count.value);
719
+ },
720
+ [],
721
+ );
722
+
723
+ return react.Fragment ({}, [
724
+ react.button (
725
+ {'ref' : (ref) => incrementButtonRef = ref, 'onClick' : (_) => count.setWithUpdater ((prev) => prev + 1 )},
726
+ ['+' ]),
727
+ react.button ({
728
+ 'ref' : (ref) => reRenderButtonRef = ref,
729
+ 'onClick' : (_) => reRender.setWithUpdater ((prev) => prev + 1 )
730
+ }, [
731
+ 're-render'
732
+ ]),
733
+ ]);
734
+ });
735
+
736
+ react_dom.render (UseMemoTest ({}), mountNode);
737
+ });
738
+
739
+ test ('correctly initializes memoized value' , () {
740
+ expect (count.value, 5 );
741
+
742
+ expect (returnValueWithDeps, 8 );
743
+ expect (returnValueNoDeps, 8 );
744
+ expect (returnValueEmptyDeps, 8 );
745
+
746
+ expect (createFunctionCallCountWithDeps, 1 );
747
+ expect (createFunctionCallCountNoDeps, 1 );
748
+ expect (createFunctionCallCountEmptyDeps, 1 );
749
+ });
750
+
751
+ group ('after depending state changes,' , () {
752
+ setUpAll (() {
753
+ react_test_utils.Simulate .click (incrementButtonRef);
754
+ });
755
+
756
+ test ('createFunction does not run if state not in dependency list' , () {
757
+ expect (returnValueEmptyDeps, 8 );
758
+
759
+ expect (createFunctionCallCountEmptyDeps, 1 , reason: 'count.value is not in dependency list' );
760
+ });
761
+
762
+ test ('createFunction re-runs if state is in dependency list or if there is no dependency list' , () {
763
+ expect (returnValueWithDeps, 13 );
764
+ expect (returnValueNoDeps, 13 );
765
+
766
+ expect (createFunctionCallCountWithDeps, 2 , reason: 'count.value is in dependency list' );
767
+ expect (createFunctionCallCountNoDeps, 2 ,
768
+ reason: 'createFunction runs on every render because there is no dependency list' );
769
+ });
770
+ });
771
+
772
+ group ('after component re-renders,' , () {
773
+ setUpAll (() {
774
+ react_test_utils.Simulate .click (reRenderButtonRef);
775
+ });
776
+
777
+ test ('createFunction re-runs if there is no dependency list' , () {
778
+ expect (returnValueNoDeps, 13 , reason: 'count.value stayed the same so the same value is returned' );
779
+
780
+ expect (createFunctionCallCountNoDeps, 3 ,
781
+ reason: 'createFunction runs on every render because there is no dependency list' );
782
+ });
783
+
784
+ test ('createFunction does not run if there is a dependency list' , () {
785
+ expect (returnValueEmptyDeps, 8 );
786
+ expect (returnValueWithDeps, 13 );
787
+
788
+ expect (createFunctionCallCountEmptyDeps, 1 , reason: 'no dependency changed' );
789
+ expect (createFunctionCallCountWithDeps, 2 , reason: 'no dependency changed' );
790
+ });
791
+ });
792
+ });
669
793
});
670
794
}
671
795
0 commit comments