@@ -15,6 +15,7 @@ let ReactNoop;
15
15
let Scheduler ;
16
16
let Suspense ;
17
17
let useState ;
18
+ let useLayoutEffect ;
18
19
let useTransition ;
19
20
let startTransition ;
20
21
let act ;
@@ -30,6 +31,7 @@ describe('ReactTransition', () => {
30
31
ReactNoop = require ( 'react-noop-renderer' ) ;
31
32
Scheduler = require ( 'scheduler' ) ;
32
33
useState = React . useState ;
34
+ useLayoutEffect = React . useLayoutEffect ;
33
35
useTransition = React . unstable_useTransition ;
34
36
Suspense = React . Suspense ;
35
37
startTransition = React . unstable_startTransition ;
@@ -773,4 +775,188 @@ describe('ReactTransition', () => {
773
775
} ) ;
774
776
} ,
775
777
) ;
778
+
779
+ // @gate experimental
780
+ // @gate enableCache
781
+ it ( 'should render normal pri updates scheduled after transitions before transitions' , async ( ) => {
782
+ let updateTransitionPri ;
783
+ let updateNormalPri ;
784
+ function App ( ) {
785
+ const [ normalPri , setNormalPri ] = useState ( 0 ) ;
786
+ const [ transitionPri , setTransitionPri ] = useState ( 0 ) ;
787
+ updateTransitionPri = ( ) =>
788
+ startTransition ( ( ) => setTransitionPri ( n => n + 1 ) ) ;
789
+ updateNormalPri = ( ) => setNormalPri ( n => n + 1 ) ;
790
+
791
+ useLayoutEffect ( ( ) => {
792
+ Scheduler . unstable_yieldValue ( 'Commit' ) ;
793
+ } ) ;
794
+
795
+ return (
796
+ < Suspense fallback = { < Text text = "Loading..." /> } >
797
+ < Text text = { 'Transition pri: ' + transitionPri } />
798
+ { ', ' }
799
+ < Text text = { 'Normal pri: ' + normalPri } />
800
+ </ Suspense >
801
+ ) ;
802
+ }
803
+
804
+ const root = ReactNoop . createRoot ( ) ;
805
+ await act ( async ( ) => {
806
+ root . render ( < App /> ) ;
807
+ } ) ;
808
+
809
+ // Initial render.
810
+ expect ( Scheduler ) . toHaveYielded ( [
811
+ 'Transition pri: 0' ,
812
+ 'Normal pri: 0' ,
813
+ 'Commit' ,
814
+ ] ) ;
815
+ expect ( root ) . toMatchRenderedOutput ( 'Transition pri: 0, Normal pri: 0' ) ;
816
+
817
+ await act ( async ( ) => {
818
+ updateTransitionPri ( ) ;
819
+ updateNormalPri ( ) ;
820
+ } ) ;
821
+
822
+ expect ( Scheduler ) . toHaveYielded ( [
823
+ // Normal update first.
824
+ 'Transition pri: 0' ,
825
+ 'Normal pri: 1' ,
826
+ 'Commit' ,
827
+
828
+ // Then transition update.
829
+ 'Transition pri: 1' ,
830
+ 'Normal pri: 1' ,
831
+ 'Commit' ,
832
+ ] ) ;
833
+ expect ( root ) . toMatchRenderedOutput ( 'Transition pri: 1, Normal pri: 1' ) ;
834
+ } ) ;
835
+
836
+ // @gate experimental
837
+ // @gate enableCache
838
+ it ( 'should render normal pri updates before transition suspense retries' , async ( ) => {
839
+ let updateTransitionPri ;
840
+ let updateNormalPri ;
841
+ function App ( ) {
842
+ const [ transitionPri , setTransitionPri ] = useState ( false ) ;
843
+ const [ normalPri , setNormalPri ] = useState ( 0 ) ;
844
+
845
+ updateTransitionPri = ( ) => startTransition ( ( ) => setTransitionPri ( true ) ) ;
846
+ updateNormalPri = ( ) => setNormalPri ( n => n + 1 ) ;
847
+
848
+ useLayoutEffect ( ( ) => {
849
+ Scheduler . unstable_yieldValue ( 'Commit' ) ;
850
+ } ) ;
851
+
852
+ return (
853
+ < Suspense fallback = { < Text text = "Loading..." /> } >
854
+ { transitionPri ? < AsyncText text = "Async" /> : < Text text = "(empty)" /> }
855
+ { ', ' }
856
+ < Text text = { 'Normal pri: ' + normalPri } />
857
+ </ Suspense >
858
+ ) ;
859
+ }
860
+
861
+ const root = ReactNoop . createRoot ( ) ;
862
+ await act ( async ( ) => {
863
+ root . render ( < App /> ) ;
864
+ } ) ;
865
+
866
+ // Initial render.
867
+ expect ( Scheduler ) . toHaveYielded ( [ '(empty)' , 'Normal pri: 0' , 'Commit' ] ) ;
868
+ expect ( root ) . toMatchRenderedOutput ( '(empty), Normal pri: 0' ) ;
869
+
870
+ await act ( async ( ) => {
871
+ updateTransitionPri ( ) ;
872
+ } ) ;
873
+
874
+ expect ( Scheduler ) . toHaveYielded ( [
875
+ // Suspend.
876
+ 'Suspend! [Async]' ,
877
+ 'Normal pri: 0' ,
878
+ 'Loading...' ,
879
+ ] ) ;
880
+ expect ( root ) . toMatchRenderedOutput ( '(empty), Normal pri: 0' ) ;
881
+
882
+ await act ( async ( ) => {
883
+ await resolveText ( 'Async' ) ;
884
+ updateNormalPri ( ) ;
885
+ } ) ;
886
+
887
+ expect ( Scheduler ) . toHaveYielded ( [
888
+ // Normal pri update.
889
+ '(empty)' ,
890
+ 'Normal pri: 1' ,
891
+ 'Commit' ,
892
+
893
+ // Promise resolved, retry flushed.
894
+ 'Async' ,
895
+ 'Normal pri: 1' ,
896
+ 'Commit' ,
897
+ ] ) ;
898
+ expect ( root ) . toMatchRenderedOutput ( 'Async, Normal pri: 1' ) ;
899
+ } ) ;
900
+
901
+ // @gate experimental
902
+ // @gate enableTransitionEntanglement
903
+ // @gate enableCache
904
+ it ( 'should not interrupt transitions with normal pri updates' , async ( ) => {
905
+ let updateNormalPri ;
906
+ let updateTransitionPri ;
907
+ function App ( ) {
908
+ const [ transitionPri , setTransitionPri ] = useState ( 0 ) ;
909
+ const [ normalPri , setNormalPri ] = useState ( 0 ) ;
910
+ updateTransitionPri = ( ) =>
911
+ startTransition ( ( ) => setTransitionPri ( n => n + 1 ) ) ;
912
+ updateNormalPri = ( ) => setNormalPri ( n => n + 1 ) ;
913
+
914
+ useLayoutEffect ( ( ) => {
915
+ Scheduler . unstable_yieldValue ( 'Commit' ) ;
916
+ } ) ;
917
+ return (
918
+ < >
919
+ < Text text = { 'Transition pri: ' + transitionPri } />
920
+ { ', ' }
921
+ < Text text = { 'Normal pri: ' + normalPri } />
922
+ </ >
923
+ ) ;
924
+ }
925
+
926
+ const root = ReactNoop . createRoot ( ) ;
927
+ await ReactNoop . act ( async ( ) => {
928
+ root . render ( < App /> ) ;
929
+ } ) ;
930
+ expect ( Scheduler ) . toHaveYielded ( [
931
+ 'Transition pri: 0' ,
932
+ 'Normal pri: 0' ,
933
+ 'Commit' ,
934
+ ] ) ;
935
+ expect ( root ) . toMatchRenderedOutput ( 'Transition pri: 0, Normal pri: 0' ) ;
936
+
937
+ await ReactNoop . act ( async ( ) => {
938
+ updateTransitionPri ( ) ;
939
+
940
+ expect ( Scheduler ) . toFlushAndYieldThrough ( [
941
+ // Start transition update.
942
+ 'Transition pri: 1' ,
943
+ ] ) ;
944
+
945
+ // Schedule normal pri update during transition update.
946
+ // This should not interrupt.
947
+ updateNormalPri ( ) ;
948
+ } ) ;
949
+
950
+ expect ( Scheduler ) . toHaveYielded ( [
951
+ // Finish transition update.
952
+ 'Normal pri: 0' ,
953
+ 'Commit' ,
954
+
955
+ // Normal pri update.
956
+ 'Transition pri: 1' ,
957
+ 'Normal pri: 1' ,
958
+ 'Commit' ,
959
+ ] ) ;
960
+ expect ( root ) . toMatchRenderedOutput ( 'Transition pri: 1, Normal pri: 1' ) ;
961
+ } ) ;
776
962
} ) ;
0 commit comments