-
Notifications
You must be signed in to change notification settings - Fork 7
New "Learn" Docs Section for Async #2
At React Conf 2025, there were a number of conversations around how we could improve the React.dev docs story around async features in React. In particular, it feels like many APIs are solely documented in the reference documentation section.
I'd like to propose that we introduce a new section in the "Learn" docs that covers:
- Suspense/Suspending
- Transitions/Actions
- Optimistic/Pending
- Concurrent Stores (eventually)
Maybe we could name this section as something like "Handling Data"? In my opinion, it would make sense to structure these pages as:
- Fetching asynchronous data (
use,Suspense,cache,cacheSignal) - Handling user interactions (
<form action>,startTransition) - Improving user experience around data (
useOptimistic,useTransition)
And going from there.
Bike-sheds on terms here are welcomed as I know naming can be critical for others' understanding.
Once we figure out a good structure for these docs, I'm happy to begin working on the docs pages related to this and we can do a more in-depth review in PRs
All reactions
-
❤️ 1 -
🚀 2
Replies: 6 comments 15 replies
I think @rickhanlonii 's talk from ReactConf is a good conceptual starting point for these docs. I'm generally picturing some sections that cover:
- Common async patterns with React
- How modern React makes those patterns simpler and provides better UX
- Introduces concepts like "transitions" in a unified way and shows what problems they help solve so that learners even know what they are and why they're useful (without knowing to look at a page like the
useTransitiondocs ahead of time)
All reactions
-
👍 1
Absolutely agree, especially on the "how React makes patterns in UX easier". I want to make sure that these pages demonstrate pragmatic challenges in even non-concurrent variants of React code.
I think we can do this with a number of Before and After demos and videos
All reactions
I'd generally try to steer in favor of "just explaining how to use it" rather than "before/after". Since the majority of React users always exist in the future, and comparing with the past does not necessarily help them understand.
The Learn section generally assumes React is the first programming language/library they're learning. This is not necessarily best for everyone, but for an increasing number of people, this will be true over time. And we want to make sure that the Learn section doesn't suffer from getting stale over time as e.g. blogs do. This is why "just show how it works" is generally favored over "here's why it's better than approach A or approach B you've been using before".
That said, sometimes there's some fundamental shift we need to explain, e.g. first part of https://react.dev/learn/reacting-to-input-with-state is a concession to that (understanding imperative vs declarative is too useful, even if you're not writing imperative UI code). I don't think it hurts to have these, but we should always think about what it feels for someone who's learning programming now and this is their first UI framework.
If we think Async React is better, we should be able to mostly explain it "on its own".
All reactions
-
👍 1
Thanks for starting this convo, I have some ideas for this so I'll do a brain dump.
Quick
Some quick things we can ship:
- Rewrite
use()docs reactjs/react.dev#8305 Betteruse(promise)reference docs: these docs should provide some basic examples of usinguse(promise). The only docs there assume you're passing the promise from the server. I think we could document using a global Map() cache that is useful as a replacement for fetching in an effect, and provide a deep dive on revalidation (i.e. how and when to clear the cache and trigger a refresh). - Revamp useOptimistic docs reactjs/react.dev#8264 Better
useOptimisticreference docs: these docs should provide better explanation of what useOptimistic is. It currently only documents using it with form actions, doesn't say that the reducer arg is optional, and doesn't really help you understand what it is. We also need to provide a ton more usage examples including:- Adding optimistic updates for action props: show how to use useOptimistic in a design component so the component always updates immediately while the Action is in progress. Like the tab bar from my talk demo.
- Adding optimistic updates to your app: Even if you're using an
actionprop, there are many use cases where the product code may want to add some additional optimistic state, in addition to the automatic optimistic feedback provided. For example, in my demo you might want to also cross out the item when it's marked complete while the mutation is in progress, or you might want to optimistically move the item to the complete tab. - Using the reducer: There should be a good, canonical example for when and how to use the reducer arg.
- Handling errors / mismatched: If an action errors, or the value resolves to a different value than the optimistic one (like the value from the server has changed from a different user or tab) the optimistic value will automatically commit the newest actual value passed in.
- Rewrite useActionState reactjs/react.dev#8284 Better
useActionStatereference docs: these currently only explain how to use it with form actions. We need a better explain for when to use it, and good canonical examples of when you should useuseActionStateinstead of Actions directly (like when you need to sequence Actions and reduce over the result for each submission). - Add fragment refs to You Don't Need An Effect: The Sending a POST request is doing visibility logging, but this really should be done with an intersection observer instead of an effect or your impressions will be wrong in subtle ways (this is true of all UI frameworks, not a React thing). This could be updated to use a fragment ref and
observeUsing. - Add Actions to You Don't Need an Effect: Also in Sending a POST request, when you do need to do non-logging POSTs, we should recommend moving it to an event using an async action, and explain the benefits.
- Add
use(promise)to You Don't Need an Effect: The Fetching Data explains how to fetch in an effect, I think this should get updated to how to useuse(promise)instead.
Medium-ish
These are less concrete, but fairly straight forward:
- Design Component patterns: in the old concurrent mode patterns docs we recommended that design components call callbacks in transitions, but had to walk that back because we didn't have features like async transitions or use optimistic. Now that we do, we should have some kind of recommendation somewhere, and explanations for how to implement it. We kind of have this with the
actionprop docs, but we need more. - Action props in existing Learn docs: This is tricky because the learn docs currently do a good job at incrementally introducing ideas like events and state, but in Async React world the Adding Interactivity section would be a log different. Instead of being event-handler first, I think it would be action prop first.
- Fragment refs learn docs: This could probably be in the Escape Hatches section with the other refs stuff. We also need to update the existing pages to use fragment refs where appropriate.
Bigger
Like you mentioned in the post, we need learn docs for these patterns.
I was thinking a new top level section like:
-
Handling data
- Getting remote data (Suspense)
- Handling user actions (overview of the three paint and transitions, related to next two guides)
- Submitting forms (Form actions,
useFormStatus, as in introduction toactionprops) - Creating user actions (implementing your own
actionprop) - Showing pending feedback (
useOptimistic) - Queuing sequential actions (
useActionState)
-
Improving UX
- Updating the current page (transitions in the background)
- Navigating to a new page (transition to suspense fallbacks)
- Removing fallbacks for new routes (
Activitypre-render use case) - Keep state when leaving a page (
Activity) - Adding animations (walk though css/js/view transition option)
- Animating page transitions (
ViewTransition)
Some of this is tricky because if you're using a framework, or router/data/design libraries that support these patterns, then these docs are not relevant to you - this is just the way it works. But I think we can explain that somehow, so you know why the app works the way it does when you see it.
All reactions
-
❤️ 4
Also in Sending a POST request, when you do need to do non-logging POSTs, we should recommend moving it to an event using an async action, and explain the benefits.
I'm not sure I see how actions are relevant there. The point of that example was to show separation between "things that correspond to events" and "things that correspond to effects". We're already showing an example where an event makes sense there, so converting everything to event there would miss the point of example.
From the article:
When you choose whether to put some logic into an event handler or an Effect, the main question you need to answer is what kind of logic it is from the user’s perspective. If this logic is caused by a particular interaction, keep it in the event handler. If it’s caused by the user seeing the component on the screen, keep it in the Effect.
All reactions
This is tricky because the learn docs currently do a good job at incrementally introducing ideas like events and state, but in Async React world the Adding Interactivity section would be a log different. Instead of being event-handler first, I think it would be action prop first.
I agree. See #2 (comment) for more thoughts on this. If we introduce async components, <Suspense>, and <form> in a separate section, it makes sense to introduce action there too — and to place that section before Adding Interactivity.
All reactions
Design Component patterns
One thing I think would be great is a list of examples of design system components with action props. The reason for this is that I have a feeling that there are some repeating type on prop names (action, changeAction, ?...). But I'm not yet used to think action-first (if you will). So it doesn't come naturally yet. Also, some events might almost never make sense as an action prop?
I feel like examples could really help save everyone from slowly discovering the same things. They wouldn't necessarily have to include implementation. The calling side would probably be enough.
All reactions
I just put a PR up to revamp the useOptimistic docs, would love feedback:
All reactions
-
👀 2
Update: I put up PRs for use() and useActionState():
All reactions
-
❤️ 1
Related: @rickhanlonii , did you have a chance to publish the demo app repo anywhere? If not, could you do that? Saw some folks asking to see the code.
All reactions
Yeah, I'm working on that now. Here's the repo: https://github.com/rickhanlonii/async-react
I'm just trying to deploy it before sharing but getting hung up on cloudflare configs.
All reactions
I'd add that originally (when the docs were being written) Fetching Data was supposed to be a section that comes between Describing the UI and Adding Interactivity. That's also why Describing the UI was written without any client features.
The idea was to show Suspense etc before showing state because Suspensey data fetching is router-driven (at least in RSC), and using router doesn't force you to learn about state. Explaining patterns like Transitions and Suspense just relies on having a router. (Look at examples on https://react.dev/reference/react/Suspense — most of this stuff is not related to state.)
Indeed, in the default RSC environment you can't use state directly even if you want to, so it kind of makes sense to explain async components, <Suspense> and <form> before introducing 'use client' and all the client-related features. If you start with an RSC framework (as we recommend), the first environment you land in should probably be described first.
So the idea was that Describing the UI is universal, then Fetching Data teaches you declarative data fetching and patterns around that (and animations), and the next section (Adding Interactivity) is when we teach about 'use client' and the entire client-side world. (At the time, we also thought we might have a client-only version of RSC-like Server components by then, so it would work for teaching on the client too. This isn't about selling RSCs, it's just about conceptual ordering.)
This ended up getting deprioritized because it involved making decisions for how sandboxes should work (eg. what should the mock router be like, should it use a framework or a fake framework, should it be "true RSC", "RSC in a worker", "client-side RSC-like" thing, something client-only but with right conventions, etc.)
I would highly encourage whoever decides to pick up this section to avoid tying explanations to state (even if it ends up after Interactivity in the end) or making them seem like we're explaining complex concepts. In the end it's just async/await for data fetching, declaring glimmers with <Suspense>, and some patterns around when to move <Suspense> up/down the tree or give it keys. Same for <ViewTransition>. This can be taught very early. This can also be taught in a very beginner-friendly way with no need to get PhD in React. The concepts themselves are very intuitive if you look at the actual user-facing API in a world where popular libraries are already designed for async React.
All reactions
-
👍 1
Do keep in mind that Learn section is supposed to be linear, i.e. topologically sorted with zero circular dependencies. The reader should be able to read it top to bottom without ever bumping into an explanation that depends on knowing some concept that has not been introduced yet. This is a hard constraint in the structure.
Therefore, if Fetching Data depends on state somewhere, it must either explain state somewhere in a limited way, or it must come after Adding Interactivity. Personally I think it would be better if it came before Adding Interactivity, and state-specific parts were merged into Adding Interactivity (like the "optimistic" stuff). Not all "concurrent" stuff belongs together in one section, it's just React. We just need to flag which parts depend on "new world".
All reactions
-
👍 1
Yeah makes sense +1
All reactions
Thank you for starting this @crutchcorn and for the incredible brain-dump @rickhanlonii. I can help with the following -
Add fragment refs to You Don't Need An Effect: The Sending a POST request is doing visibility logging, but this really should be done with an intersection observer instead of an effect or your impressions will be wrong in subtle ways (this is true of all UI frameworks, not a React thing). This could be updated to use a fragment ref and observeUsing.
Add Actions to You Don't Need an Effect: Also in Sending a POST request, when you do need to do non-logging POSTs, we should recommend moving it to an event using an async action, and explain the benefits.
Add use(promise) to You Don't Need an Effect: The Fetching Data explains how to fetch in an effect, I think this should get updated to how to use use(promise) instead.
I also love the Improving UX sections and would love to help write these docs -
Removing fallbacks for new routes (Activity pre-render use case)
Keep state when leaving a page (Activity)
Adding animations (walk though css/js/view transition option)
Animating page transitions (ViewTransition)
What's the best workflow here - issues, a draft PR, or a separate discussion thread?
All reactions
-
👍 3
A draft PR is best!
All reactions
Thought I'd start a separate thread from #2 (comment) around the design component patterns, this is something I personally would like to be able to reference almost daily as I'm currently working on building a design system.
Here's my list:
- Action props
- Naming conventions
- A preference for these to be the default, with events being framed as an escape hatch
- Who calls
useOptimistic, the caller or the design component? - Wherever you accept
T, also acceptPromise<T>to opt the user into builtin loading indicators. eg.<Combobox items={items}>and<Combobox items={itemsPromise}>- Prevents spinner thrashing (in comparison to the traditional
isLoadingprop) - Allows for composition and user-controlled loading states
- Improves composition across client/server boundary (no need for another component just to use/await the promise)
- Prevents spinner thrashing (in comparison to the traditional
- Built in pending indicators
- With a way to opt out with your own as per https://x.com/rickyfm/status/1980415399289319448
What am I missing?
All reactions
-
❤️ 1