-
Notifications
You must be signed in to change notification settings - Fork 30.4k
Docs: clarify using transitions when invoking server functions from event handlers #89433
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
base: canary
Are you sure you want to change the base?
Docs: clarify using transitions when invoking server functions from event handlers #89433
Conversation
|
Allow CI Workflow Run
Note: this should only be enabled once the PR is ready to go and can only be enabled by a maintainer |
|
Allow CI Workflow Run
Note: this should only be enabled once the PR is ready to go and can only be enabled by a maintainer |
|
Hi @icyJoseph, Today, the docs show examples of calling Server Functions from event handlers, but they don’t explicitly mention that these calls should be wrapped in a React transition (e.g. useTransition) to avoid blocking rendering. This PR addresses that gap by adding a short clarification in the Event Handlers section of the Updating Data guide, making the expected usage explicit. That clarification is what #89430 is aiming to capture, independent of the pasted example code. |
|
@icyJoseph The reason I linked this PR to that issue is that the issue appears to have been auto-generated or populated with an unrelated example, while still being labeled as a documentation issue in the Next.js repo. Based on that, I interpreted the underlying intent as pointing out a docs gap rather than the specific code sample. Independently of the example, the current docs do show Server Functions being invoked from event handlers without explicitly mentioning that those calls should be wrapped in a React transition. This PR just adds that missing clarification in the Event Handlers section. If you think #89430 isn’t the right issue to track this, I’m happy to unlink it or adjust the association - the docs change itself should still be useful on its own. |
|
|
||
| ### Event Handlers | ||
|
|
||
| > **Good to know**: |
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.
Instead of adding a "Good to know" callout while keeping the example that contradicts it, what about:
- Update the lead text (line 239) to explain the tradeoff upfront
- Update the example to show the recommended pattern with
useTransition
Something like...
### Event Handlers
You can invoke a Server Function from event handlers like `onClick`. While calling
a Server Function directly works, wrapping the call in a transition integrates it
with React's rendering cycle—giving you access to pending states and ensuring
consistent UI updates.Then update the example to use useTransition:
'use client'
import { incrementLike } from './actions'
import { useState, useTransition } from 'react'
export default function LikeButton({ initialLikes }: { initialLikes: number }) {
const [likes, setLikes] = useState(initialLikes)
const [isPending, startTransition] = useTransition()
return (
<>
<p>Total Likes: {likes}</p>
<button
onClick={() => {
startTransition(async () => {
const updatedLikes = await incrementLike()
setLikes(updatedLikes)
})
}}
>
{isPending ? 'Updating...' : 'Like'}
</button>
</>
)
}This way the docs lead with the recommended pattern and explain why rather than showing one thing and then cautioning against it.
One caveat worth noting: React loses the async context after an await inside startTransition, so technically the setLikes after the await isn't part of the transition anymore (see React docs on this). The isPending still works for showing loading state during the async work, but it's worth being aware of. Could be worth a brief mention or link.
Also, the existing useEffect example (lines 489-494) has the same pattern - might be worth a look there too for consistency.
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.
This makes sense, thanks for the detailed feedback.
I agree that leading with the recommended pattern is clearer than showing an example and then cautioning against it. I’ll update the Event Handlers section to explain the tradeoff upfront and adjust the example to use useTransition as suggested.
Good call on the async context caveat as well I’ll keep any mention brief and link to the relevant React docs so we don’t overcomplicate the section.
I’ll also take a look at the useEffect example you pointed out to see if we can make it consistent.
I’ll push an updated commit shortly.
|
Hi @icyJoseph, Thanks for the guidance! I updated the Event Handlers example to lead with Happy to tweak wording or add a doc link if needed. |
What?
Clarifies that Server Functions invoked from Client Components outside of form actions (for example, in event handlers) should be wrapped in a React transition.
Why?
This behavior is implicit today and can be confusing when invoking Server Functions directly from event handlers. Adding a short note helps set expectations and avoid blocking rendering.
How?
Added a “Good to know” note to the Event Handlers section of the Updating Data guide.
Fixes #89430