@@ -647,10 +647,16 @@ describe('ReactDOMForm', () => {
647
647
it ( 'form actions are transitions' , async ( ) => {
648
648
const formRef = React . createRef ( ) ;
649
649
650
+ function Status ( ) {
651
+ const { pending} = useFormStatus ( ) ;
652
+ return pending ? < Text text = "Pending..." /> : null ;
653
+ }
654
+
650
655
function App ( ) {
651
656
const [ state , setState ] = useState ( 'Initial' ) ;
652
657
return (
653
658
< form action = { ( ) => setState ( 'Updated' ) } ref = { formRef } >
659
+ < Status />
654
660
< Suspense fallback = { < Text text = "Loading..." /> } >
655
661
< AsyncText text = { state } />
656
662
</ Suspense >
@@ -667,8 +673,8 @@ describe('ReactDOMForm', () => {
667
673
// This should suspend because form actions are implicitly wrapped
668
674
// in startTransition.
669
675
await submit ( formRef . current ) ;
670
- assertLog ( [ 'Suspend! [Updated]' , 'Loading...' ] ) ;
671
- expect ( container . textContent ) . toBe ( 'Initial' ) ;
676
+ assertLog ( [ 'Pending...' , ' Suspend! [Updated]', 'Loading...' ] ) ;
677
+ expect ( container . textContent ) . toBe ( 'Pending... Initial' ) ;
672
678
673
679
await act ( ( ) => resolveText ( 'Updated' ) ) ;
674
680
assertLog ( [ 'Updated' ] ) ;
@@ -680,10 +686,16 @@ describe('ReactDOMForm', () => {
680
686
it ( 'multiple form actions' , async ( ) => {
681
687
const formRef = React . createRef ( ) ;
682
688
689
+ function Status ( ) {
690
+ const { pending} = useFormStatus ( ) ;
691
+ return pending ? < Text text = "Pending..." /> : null ;
692
+ }
693
+
683
694
function App ( ) {
684
695
const [ state , setState ] = useState ( 0 ) ;
685
696
return (
686
697
< form action = { ( ) => setState ( n => n + 1 ) } ref = { formRef } >
698
+ < Status />
687
699
< Suspense fallback = { < Text text = "Loading..." /> } >
688
700
< AsyncText text = { 'Count: ' + state } />
689
701
</ Suspense >
@@ -699,17 +711,17 @@ describe('ReactDOMForm', () => {
699
711
700
712
// Update
701
713
await submit ( formRef . current ) ;
702
- assertLog ( [ 'Suspend! [Count: 1]' , 'Loading...' ] ) ;
703
- expect ( container . textContent ) . toBe ( 'Count: 0' ) ;
714
+ assertLog ( [ 'Pending...' , ' Suspend! [Count: 1]', 'Loading...' ] ) ;
715
+ expect ( container . textContent ) . toBe ( 'Pending... Count: 0' ) ;
704
716
705
717
await act ( ( ) => resolveText ( 'Count: 1' ) ) ;
706
718
assertLog ( [ 'Count: 1' ] ) ;
707
719
expect ( container . textContent ) . toBe ( 'Count: 1' ) ;
708
720
709
721
// Update again
710
722
await submit ( formRef . current ) ;
711
- assertLog ( [ 'Suspend! [Count: 2]' , 'Loading...' ] ) ;
712
- expect ( container . textContent ) . toBe ( 'Count: 1' ) ;
723
+ assertLog ( [ 'Pending...' , ' Suspend! [Count: 2]', 'Loading...' ] ) ;
724
+ expect ( container . textContent ) . toBe ( 'Pending... Count: 1' ) ;
713
725
714
726
await act ( ( ) => resolveText ( 'Count: 2' ) ) ;
715
727
assertLog ( [ 'Count: 2' ] ) ;
@@ -720,6 +732,11 @@ describe('ReactDOMForm', () => {
720
732
it ( 'form actions can be asynchronous' , async ( ) => {
721
733
const formRef = React . createRef ( ) ;
722
734
735
+ function Status ( ) {
736
+ const { pending} = useFormStatus ( ) ;
737
+ return pending ? < Text text = "Pending..." /> : null ;
738
+ }
739
+
723
740
function App ( ) {
724
741
const [ state , setState ] = useState ( 'Initial' ) ;
725
742
return (
@@ -730,6 +747,7 @@ describe('ReactDOMForm', () => {
730
747
startTransition ( ( ) => setState ( 'Updated' ) ) ;
731
748
} }
732
749
ref = { formRef } >
750
+ < Status />
733
751
< Suspense fallback = { < Text text = "Loading..." /> } >
734
752
< AsyncText text = { state } />
735
753
</ Suspense >
@@ -744,11 +762,15 @@ describe('ReactDOMForm', () => {
744
762
expect ( container . textContent ) . toBe ( 'Initial' ) ;
745
763
746
764
await submit ( formRef . current ) ;
747
- assertLog ( [ 'Async action started' ] ) ;
765
+ assertLog ( [ 'Async action started' , 'Pending...' ] ) ;
748
766
749
767
await act ( ( ) => resolveText ( 'Wait' ) ) ;
750
768
assertLog ( [ 'Suspend! [Updated]' , 'Loading...' ] ) ;
751
- expect ( container . textContent ) . toBe ( 'Initial' ) ;
769
+ expect ( container . textContent ) . toBe ( 'Pending...Initial' ) ;
770
+
771
+ await act ( ( ) => resolveText ( 'Updated' ) ) ;
772
+ assertLog ( [ 'Updated' ] ) ;
773
+ expect ( container . textContent ) . toBe ( 'Updated' ) ;
752
774
} ) ;
753
775
754
776
it ( 'sync errors in form actions can be captured by an error boundary' , async ( ) => {
@@ -851,17 +873,53 @@ describe('ReactDOMForm', () => {
851
873
852
874
// @gate enableFormActions
853
875
// @gate enableAsyncActions
854
- it ( 'useFormStatus exists' , async ( ) => {
855
- // This API isn't fully implemented yet. This just tests that it's wired
856
- // up correctly.
876
+ it ( 'useFormStatus reads the status of a pending form action' , async ( ) => {
877
+ const formRef = React . createRef ( ) ;
878
+
879
+ function Status ( ) {
880
+ const { pending, data, action, method} = useFormStatus ( ) ;
881
+ if ( ! pending ) {
882
+ return < Text text = "No pending action" /> ;
883
+ } else {
884
+ const foo = data . get ( 'foo' ) ;
885
+ return (
886
+ < Text
887
+ text = { `Pending action ${ action . name } : foo is ${ foo } , method is ${ method } ` }
888
+ />
889
+ ) ;
890
+ }
891
+ }
892
+
893
+ async function myAction ( ) {
894
+ Scheduler . log ( 'Async action started' ) ;
895
+ await getText ( 'Wait' ) ;
896
+ Scheduler . log ( 'Async action finished' ) ;
897
+ }
857
898
858
899
function App ( ) {
859
- const { pending} = useFormStatus ( ) ;
860
- return 'Pending: ' + pending ;
900
+ return (
901
+ < form action = { myAction } ref = { formRef } >
902
+ < input type = "text" name = "foo" defaultValue = "bar" />
903
+ < Status />
904
+ </ form >
905
+ ) ;
861
906
}
862
907
863
908
const root = ReactDOMClient . createRoot ( container ) ;
864
909
await act ( ( ) => root . render ( < App /> ) ) ;
865
- expect ( container . textContent ) . toBe ( 'Pending: false' ) ;
910
+ assertLog ( [ 'No pending action' ] ) ;
911
+ expect ( container . textContent ) . toBe ( 'No pending action' ) ;
912
+
913
+ await submit ( formRef . current ) ;
914
+ assertLog ( [
915
+ 'Async action started' ,
916
+ 'Pending action myAction: foo is bar, method is get' ,
917
+ ] ) ;
918
+ expect ( container . textContent ) . toBe (
919
+ 'Pending action myAction: foo is bar, method is get' ,
920
+ ) ;
921
+
922
+ await act ( ( ) => resolveText ( 'Wait' ) ) ;
923
+ assertLog ( [ 'Async action finished' , 'No pending action' ] ) ;
866
924
} ) ;
867
925
} ) ;
0 commit comments