New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[WIP] Add async transitions to React 19 docs #6837
base: v19
Are you sure you want to change the base?
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
@rickhanlonii is attempting to deploy a commit to the Meta Open Source Team on Vercel. A member of the Team first needs to authorize it. |
#### Parameters {/*starttransition-parameters*/} | ||
|
||
* `scope`: A function that updates some state by calling one or more [`set` functions.](/reference/react/useState#setstate) React immediately calls `scope` with no parameters and marks all state updates scheduled synchronously during the `scope` function call as Transitions. They will be [non-blocking](#marking-a-state-update-as-a-non-blocking-transition) and [will not display unwanted loading indicators.](#preventing-unwanted-loading-indicators) | ||
* `scope`: A function that updates some state by calling one or more [`set` functions](/reference/react/useState#setstate). React immediately calls `scope` with no parameters and marks all state updates scheduled synchronously during the `scope` function call as Transitions. Any async calls awaited in the `scope` will be included in the transition, but currently require wrapping any `set` functions after the request 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](#marking-a-state-update-as-a-non-blocking-transition) and [will not display unwanted loading indicators.](#preventing-unwanted-loading-indicators). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* `scope`: A function that updates some state by calling one or more [`set` functions](/reference/react/useState#setstate). React immediately calls `scope` with no parameters and marks all state updates scheduled synchronously during the `scope` function call as Transitions. Any async calls awaited in the `scope` will be included in the transition, but currently require wrapping any `set` functions after the request 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](#marking-a-state-update-as-a-non-blocking-transition) and [will not display unwanted loading indicators.](#preventing-unwanted-loading-indicators). | |
* `scope`: A function that updates some State by calling one or more [`set` functions](/reference/react/useState#setstate). React immediately calls `scope` with no parameters and marks all state updates scheduled synchronously during the `scope` function call as Transitions. Any async calls awaited in the `scope` will be included in the transition, but currently require wrapping any `set` functions after the request 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](#marking-a-state-update-as-a-non-blocking-transition) and [will not display unwanted loading indicators.](#preventing-unwanted-loading-indicators). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see a lot of state references from react to be in smallcase? Is this intentional?
startTransition(() => { | ||
setQuantity(savedQuantity); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's probably useful to add a small note in this sandbox that explains why we need the extra startTransition
here. I was looking for this info but it only appears later in the troubleshooting section.
I also tried to remove the extra startTransition()
to see if I got a bug, but in this case I didn't really see any behavior change. It's probably only due to that specific example since setQuantity
happens last
To be honest I really don't see async transitions (with useTransition) being practically adoptable without the race condition handling built in. Without this, they are simply a target for libraries as the queue handling is very tricky. There are so many footguns with using them on their own that I think there needs to be some massive disclaimer, and for them to be called out as a tool for library and framework authors. |
@tom-sherman it's going to be more common for app developers to use |
It's similar to how doing event handlers to submit data on your own is tricky (for example, this case isn't handled in a raw event handler either), and libraries make that easier using raw events and exposing props to limit the complexity to app developers. |
Converting back to WIP, I think there is a better way to explain this. |
startTransition(async () => { | ||
await someAsyncFunction(); | ||
// ✅ Using startTransition *after* await | ||
startTransition(() => { | ||
setPage('/about'); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Something that isn't immediately clear to me:
Do we need this nested startTransition
for:
- regular form actions too?
- calling
setOptimisticValue
?
I assume we do, but not 100% sure since I don't see any example in the docs.
The <form>
actions examples are likely to use useActionState
instead of doing startTransition(() => setState())
The useOptimistic
doc only calls the setter as the first step, probably the most common case, but maybe it can make sense in some rare cases to call it after await
? I don't know 🤷♂️
async function formAction(formData) {
addOptimisticMessage(formData.get("message"));
formRef.current.reset();
await sendMessage(formData);
}
Preview
This isn't final, I'm still iterating on the best way to explain this so please resist the urge to share as if it's the actual explanation
Overview
This PR updates the
useTransition
docs to include async transitions.