@@ -647,10 +647,16 @@ describe('ReactDOMForm', () => {
647647 it ( 'form actions are transitions' , async ( ) => {
648648 const formRef = React . createRef ( ) ;
649649
650+ function Status ( ) {
651+ const { pending} = useFormStatus ( ) ;
652+ return pending ? < Text text = "Pending..." /> : null ;
653+ }
654+
650655 function App ( ) {
651656 const [ state , setState ] = useState ( 'Initial' ) ;
652657 return (
653658 < form action = { ( ) => setState ( 'Updated' ) } ref = { formRef } >
659+ < Status />
654660 < Suspense fallback = { < Text text = "Loading..." /> } >
655661 < AsyncText text = { state } />
656662 </ Suspense >
@@ -667,8 +673,8 @@ describe('ReactDOMForm', () => {
667673 // This should suspend because form actions are implicitly wrapped
668674 // in startTransition.
669675 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' ) ;
672678
673679 await act ( ( ) => resolveText ( 'Updated' ) ) ;
674680 assertLog ( [ 'Updated' ] ) ;
@@ -680,10 +686,16 @@ describe('ReactDOMForm', () => {
680686 it ( 'multiple form actions' , async ( ) => {
681687 const formRef = React . createRef ( ) ;
682688
689+ function Status ( ) {
690+ const { pending} = useFormStatus ( ) ;
691+ return pending ? < Text text = "Pending..." /> : null ;
692+ }
693+
683694 function App ( ) {
684695 const [ state , setState ] = useState ( 0 ) ;
685696 return (
686697 < form action = { ( ) => setState ( n => n + 1 ) } ref = { formRef } >
698+ < Status />
687699 < Suspense fallback = { < Text text = "Loading..." /> } >
688700 < AsyncText text = { 'Count: ' + state } />
689701 </ Suspense >
@@ -699,17 +711,17 @@ describe('ReactDOMForm', () => {
699711
700712 // Update
701713 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' ) ;
704716
705717 await act ( ( ) => resolveText ( 'Count: 1' ) ) ;
706718 assertLog ( [ 'Count: 1' ] ) ;
707719 expect ( container . textContent ) . toBe ( 'Count: 1' ) ;
708720
709721 // Update again
710722 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' ) ;
713725
714726 await act ( ( ) => resolveText ( 'Count: 2' ) ) ;
715727 assertLog ( [ 'Count: 2' ] ) ;
@@ -720,6 +732,11 @@ describe('ReactDOMForm', () => {
720732 it ( 'form actions can be asynchronous' , async ( ) => {
721733 const formRef = React . createRef ( ) ;
722734
735+ function Status ( ) {
736+ const { pending} = useFormStatus ( ) ;
737+ return pending ? < Text text = "Pending..." /> : null ;
738+ }
739+
723740 function App ( ) {
724741 const [ state , setState ] = useState ( 'Initial' ) ;
725742 return (
@@ -730,6 +747,7 @@ describe('ReactDOMForm', () => {
730747 startTransition ( ( ) => setState ( 'Updated' ) ) ;
731748 } }
732749 ref = { formRef } >
750+ < Status />
733751 < Suspense fallback = { < Text text = "Loading..." /> } >
734752 < AsyncText text = { state } />
735753 </ Suspense >
@@ -744,11 +762,15 @@ describe('ReactDOMForm', () => {
744762 expect ( container . textContent ) . toBe ( 'Initial' ) ;
745763
746764 await submit ( formRef . current ) ;
747- assertLog ( [ 'Async action started' ] ) ;
765+ assertLog ( [ 'Async action started' , 'Pending...' ] ) ;
748766
749767 await act ( ( ) => resolveText ( 'Wait' ) ) ;
750768 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' ) ;
752774 } ) ;
753775
754776 it ( 'sync errors in form actions can be captured by an error boundary' , async ( ) => {
@@ -851,17 +873,53 @@ describe('ReactDOMForm', () => {
851873
852874 // @gate enableFormActions
853875 // @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+ }
857898
858899 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+ ) ;
861906 }
862907
863908 const root = ReactDOMClient . createRoot ( container ) ;
864909 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' ] ) ;
866924 } ) ;
867925} ) ;
0 commit comments