@@ -77,8 +77,8 @@ function SubmitButton({ submitAction }) {
77
77
< button
78
78
disabled= {isPending}
79
79
onClick= {() => {
80
- startTransition (() => {
81
- submitAction ();
80
+ startTransition (async () => {
81
+ await submitAction ();
82
82
});
83
83
}}
84
84
>
@@ -227,9 +227,9 @@ import { startTransition } from "react";
227
227
228
228
export default function Item ({action}) {
229
229
function handleChange (event ) {
230
- // To expose an action prop, call the callback in startTransition.
230
+ // To expose an action prop, await the callback in startTransition.
231
231
startTransition (async () => {
232
- action (event .target .value );
232
+ await action (event .target .value );
233
233
})
234
234
}
235
235
return (
@@ -585,19 +585,20 @@ This solution makes the app feel slow, because the user must wait each time they
585
585
586
586
You can expose an ` action ` prop from a component to allow a parent to call an Action.
587
587
588
-
589
588
For example, this ` TabButton ` component wraps its ` onClick ` logic in an ` action ` prop:
590
589
591
- ``` js {8-10 }
590
+ ``` js {8-12 }
592
591
export default function TabButton ({ action, children, isActive }) {
593
592
const [isPending , startTransition ] = useTransition ();
594
593
if (isActive) {
595
594
return < b> {children}< / b>
596
595
}
597
596
return (
598
597
< button onClick= {() => {
599
- startTransition (() => {
600
- action ();
598
+ startTransition (async () => {
599
+ // await the action that's passed in.
600
+ // This allows it to be either sync or async.
601
+ await action ();
601
602
});
602
603
}}>
603
604
{children}
@@ -656,10 +657,15 @@ export default function TabButton({ action, children, isActive }) {
656
657
if (isActive) {
657
658
return < b> {children}< / b>
658
659
}
660
+ if (isPending) {
661
+ return < b className= " pending" > {children}< / b> ;
662
+ }
659
663
return (
660
- < button onClick= {() => {
661
- startTransition (() => {
662
- action ();
664
+ < button onClick= {async () => {
665
+ startTransition (async () => {
666
+ // await the action that's passed in.
667
+ // This allows it to be either sync or async.
668
+ await action ();
663
669
});
664
670
}}>
665
671
{children}
@@ -729,10 +735,19 @@ export default function ContactTab() {
729
735
``` css
730
736
button { margin-right : 10px }
731
737
b { display : inline-block ; margin-right : 10px ; }
738
+ .pending { color : #777 ; }
732
739
```
733
740
734
741
</Sandpack >
735
742
743
+ <Note >
744
+
745
+ When exposing an ` action ` prop from a component, you should ` await ` it inside the transition.
746
+
747
+ This allows the ` action ` callback to be either synchronous or asynchronous without requiring an additional ` startTransition ` to wrap the ` await ` in the action.
748
+
749
+ </Note >
750
+
736
751
---
737
752
738
753
### Displaying a pending visual state {/* displaying-a-pending-visual-state* /}
@@ -804,8 +819,8 @@ export default function TabButton({ action, children, isActive }) {
804
819
}
805
820
return (
806
821
< button onClick= {() => {
807
- startTransition (() => {
808
- action ();
822
+ startTransition (async () => {
823
+ await action ();
809
824
});
810
825
}}>
811
826
{children}
@@ -1095,8 +1110,8 @@ export default function TabButton({ action, children, isActive }) {
1095
1110
}
1096
1111
return (
1097
1112
< button onClick= {() => {
1098
- startTransition (() => {
1099
- action ();
1113
+ startTransition (async () => {
1114
+ await action ();
1100
1115
});
1101
1116
}}>
1102
1117
{children}
@@ -1822,8 +1837,8 @@ import {startTransition} from 'react';
1822
1837
export default function Item ({action}) {
1823
1838
function handleChange (e ) {
1824
1839
// Update the quantity in an Action.
1825
- startTransition (() => {
1826
- action (e .target .value );
1840
+ startTransition (async () => {
1841
+ await action (e .target .value );
1827
1842
});
1828
1843
}
1829
1844
return (
0 commit comments