You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs: update startTransition async guidance for React 19
Clarify that useTransition supports async Actions in React 19, including
state updates after await. Reserve the post-await wrapping requirement for
standalone startTransition. Rephrase troubleshooting to avoid implying
async callbacks are disallowed.
Fixes#7172
Copy file name to clipboardExpand all lines: src/content/reference/react/startTransition.md
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -41,7 +41,7 @@ function TabContainer() {
41
41
42
42
#### Parameters {/*parameters*/}
43
43
44
-
*`action`: A function that updates some state by calling one or more [`set` functions](/reference/react/useState#setstate). React calls `action` immediately with no parameters and marks all state updates scheduled synchronously during the `action`function call as Transitions. Any async calls awaited in the `action` will be included in the transition, but currently require wrapping any `set` functions after the `await` in an additional `startTransition` (see [Troubleshooting](/reference/react/useTransition#react-doesnt-treat-my-state-update-after-await-as-a-transition)). State updates marked as Transitions will be [non-blocking](#marking-a-state-update-as-a-non-blocking-transition) and [will not display unwanted loading indicators.](/reference/react/useTransition#preventing-unwanted-loading-indicators).
44
+
*`action`: A function that updates some state by calling one or more [`set` functions](/reference/react/useState#setstate). The function can be synchronous or asynchronous. React calls `action` immediately with no parameters and marks all state updates scheduled during the `action` as Transitions. State updates marked as Transitions will be [non-blocking](#marking-a-state-update-as-a-non-blocking-transition) and [will not display unwanted loading indicators.](/reference/react/useTransition#preventing-unwanted-loading-indicators). If you need to track a pending Transition, use [`useTransition`](/reference/react/useTransition) instead.
45
45
46
46
#### Returns {/*returns*/}
47
47
@@ -55,7 +55,7 @@ function TabContainer() {
55
55
56
56
* The function you pass to `startTransition` is called immediately, marking all state updates that happen while it executes as Transitions. If you try to perform state updates in a `setTimeout`, for example, they won't be marked as Transitions.
57
57
58
-
*You must wrap any state updates after any async requests in another `startTransition` to mark them as Transitions. This is a known limitation that we will fix in the future (see [Troubleshooting](/reference/react/useTransition#react-doesnt-treat-my-state-update-after-await-as-a-transition)).
58
+
*When using the standalone `startTransition` function, state updates after `await` are not automatically marked as Transitions. Wrap them in another `startTransition` call (see [Troubleshooting](/reference/react/useTransition#react-doesnt-treat-my-state-update-after-await-as-a-transition)). If you use [`useTransition`](/reference/react/useTransition) in React 19, the `startTransition` function it returns supports async Actions, and state updates after `await` are included in the Transition automatically.
59
59
60
60
* A state update marked as a Transition will be interrupted by other state updates. For example, if you update a chart component inside a Transition, but then start typing into an input while the chart is in the middle of a re-render, React will restart the rendering work on the chart component after handling the input state update.
Copy file name to clipboardExpand all lines: src/content/reference/react/useActionState.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -103,7 +103,7 @@ Each time you call `dispatchAction`, React calls the `reducerAction` with the `a
103
103
* `reducerAction` can be sync or async. It can perform sync actions like showing a notification, or async actions like posting updates to a server.
104
104
* `reducerAction` is not invoked twice in `<StrictMode>` since `reducerAction` is designed to allow side effects.
105
105
* The return type of `reducerAction` must match the type of `initialState`. If TypeScript infers a mismatch, you may need to explicitly annotate your state type.
106
-
* If you set state after `await` in the `reducerAction` you currently need to wrap the state update in an additional `startTransition`. See the [startTransition](/reference/react/useTransition#react-doesnt-treat-my-state-update-after-await-as-a-transition) docs for more info.
106
+
* If you call `reducerAction` outside of a Transition (for example, directly in an event handler), wrap it in [`startTransition`](/reference/react/startTransition). See [Troubleshooting](/reference/react/useActionState#async-function-outside-transition) for more info.
107
107
* When using Server Functions, `actionPayload` needs to be [serializable](/reference/rsc/use-server#serializable-parameters-and-return-values) (values like plain objects, arrays, strings, and numbers).
Copy file name to clipboardExpand all lines: src/content/reference/react/useTransition.md
+19-9Lines changed: 19 additions & 9 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -95,7 +95,7 @@ function SubmitButton({ submitAction }) {
95
95
96
96
#### Parameters {/*starttransition-parameters*/}
97
97
98
-
*`action`: A function that updates some state by calling one or more [`set` functions](/reference/react/useState#setstate). React calls `action` immediately with no parameters and marks all state updates scheduled synchronously during the `action`function call as Transitions. Any async calls that are awaited in the `action` will be included in the Transition, but currently require wrapping any `set` functions after the `await` in an additional `startTransition` (see [Troubleshooting](#react-doesnt-treat-my-state-update-after-await-as-a-transition)). State updates marked as Transitions will be [non-blocking](#perform-non-blocking-updates-with-actions) and [will not display unwanted loading indicators](#preventing-unwanted-loading-indicators).
98
+
*`action`: A function that updates some state by calling one or more [`set` functions](/reference/react/useState#setstate). The function can be synchronous or asynchronous. React calls `action` immediately with no parameters and marks all state updates scheduled during the `action` as Transitions, including updates after `await`. State updates marked as Transitions will be [non-blocking](#perform-non-blocking-updates-with-actions) and [will not display unwanted loading indicators](#preventing-unwanted-loading-indicators).
99
99
100
100
#### Returns {/*starttransition-returns*/}
101
101
@@ -109,8 +109,6 @@ function SubmitButton({ submitAction }) {
109
109
110
110
* The function you pass to `startTransition` is called immediately, marking all state updates that happen while it executes as Transitions. If you try to perform state updates in a `setTimeout`, for example, they won't be marked as Transitions.
111
111
112
-
* You must wrap any state updates after any async requests in another `startTransition` to mark them as Transitions. This is a known limitation that we will fix in the future (see [Troubleshooting](#react-doesnt-treat-my-state-update-after-await-as-a-transition)).
113
-
114
112
* The `startTransition` function has a stable identity, so you will often see it omitted from Effect dependencies, but including it will not cause the Effect to fire. If the linter lets you omit a dependency without errors, it is safe to do. [Learn more about removing Effect dependencies.](/learn/removing-effect-dependencies#move-dynamic-objects-and-functions-inside-your-effect)
115
113
116
114
* A state update marked as a Transition will be interrupted by other state updates. For example, if you update a chart component inside a Transition, but then start typing into an input while the chart is in the middle of a re-render, React will restart the rendering work on the chart component after handling the input update.
@@ -1676,7 +1674,7 @@ startTransition(() => {
1676
1674
});
1677
1675
```
1678
1676
1679
-
The function you pass to `startTransition` must be synchronous. You can't mark an update as a Transition like this:
1677
+
The function you pass to `startTransition`is called immediately, but updates must be scheduled *during* that call. You can't mark an update as a Transition if you defer it with `setTimeout`:
1680
1678
1681
1679
```js
1682
1680
startTransition(() => {
@@ -1702,17 +1700,31 @@ setTimeout(() => {
1702
1700
1703
1701
### React doesn't treat my state update after `await` as a Transition {/*react-doesnt-treat-my-state-update-after-await-as-a-transition*/}
1704
1702
1705
-
When you use `await` inside a `startTransition` function, the state updates that happen after the `await` are not marked as Transitions. You must wrap state updates after each `await` in a `startTransition` call:
1703
+
In React 19, the `startTransition` function returned by `useTransition` supports async Actions. State updates after `await` are automatically included in the Transition:
// ✅ Updates after await are part of the Transition
1711
+
setPage('/about');
1712
+
});
1713
+
```
1714
+
1715
+
This limitation only applies to the standalone [`startTransition`](/reference/react/startTransition) function. When you use it outside a component, state updates after `await` are not automatically marked as Transitions. Wrap them in another `startTransition` call:
1706
1716
1707
1717
```js
1718
+
import { startTransition } from'react';
1719
+
1708
1720
startTransition(async () => {
1709
1721
awaitsomeAsyncFunction();
1710
-
// ❌ Not using startTransition after await
1722
+
// ❌ Not marked as a Transition with standalone startTransition
This is a JavaScript limitation due to React losing the scope of the async context. In the future, when [AsyncContext](https://github.com/tc39/proposal-async-context) is available, this limitation will be removed.
1728
-
1729
1739
---
1730
1740
1731
1741
### I want to call `useTransition` from outside a component {/*i-want-to-call-usetransition-from-outside-a-component*/}
0 commit comments