Repository navigation
[Suggestion]: Should server functions be wrapped in transitions? (conflicting info in the docs) #7734
Description
Activity
- changed the title
[-][Typo]: Should server functions be wrapped in transitions or not? (conflicting info in the docs)[/-][+][Typo]: Should server functions be wrapped in transitions? (conflicting info in the docs)[/+]on Apr 11, 2025 - changed the title
[-][Typo]: Should server functions be wrapped in transitions? (conflicting info in the docs)[/-][+][Suggestion]: Should server functions be wrapped in transitions? (conflicting info in the docs)[/+]on Apr 11, 2025 @poteto Sorry for direct tag - but would be nice if someone can have a look
Yeah good question. The recommendation is to call it in a transition, but it's not necessary. There was a common misunderstanding that Server Functions needed to be actions (which is why we renamed the concept away from Server Action).
The example in the docs that don't use a transition is showing that it doesn't need to be in a transition, but it's probably a bad example because that case should be a transition. That page includes examples with and without transitions to show both.
So I'd recommend that we:
- Update the language here to frame it more as a recommendation. It's also weird IMO to frame the two use cases as "in a form" and "outside a form". I would structure it as:
- Calling a server function
- server functions can be called directly
- we recommend server functions that will update the UI to be called in an action
- Calling a server function in an action
- show using the action prop pattern to show a pending state automatically
- Calling a server function in a form action
- same as last example, but using
<form>
- same as last example, but using
- Calling a server function
- Update the example here to do something different, like logging that doesn't need UI (as well as the one after it).
- Update the language here to frame it more as a recommendation. It's also weird IMO to frame the two use cases as "in a form" and "outside a form". I would structure it as:
Thanks for response.
I think you did not finish the sentence here:
Calling a server function in a form action
- same as last example, but using... // incomplete
Also, when a function is passed to
actionprop of a form, is this function automatically wrapped in transition during submit? I think that happens when you useuseActionState, but not sure if that happens without it.PS. I also opened another issue while ago, imho it was react bug, I will tag you there too with your permission.
Oh haha, I did finish it but I didn't escape the
<form>so github rendered it an HTML form and stripped it. Fixed!is this function automatically wrapped in transition during submit?
Yes, the prop exposed from
formis calledactionso it's implemented using theactionprop pattern in the docs here (meaning it's wrapped in a transition).What's the other issue? My notifications are out of control so I don't want to miss it.
Yes, the prop exposed from form is called action so it's implemented using the action prop pattern in the docs here (meaning it's wrapped in a transition).
Hm, ok, but should not that info be in the docs? It's not here.
Because sometimes there are examples like from here:
function formAction(formData) { addOptimisticMessage(formData.get("message")); formRef.current.reset(); startTransition(async () => { await sendMessageAction(formData); }); }which might lead someone think that
formActionis not wrapped in a transition, due to the explicitstartTransitionin the end.
Apart from that, here is the issue I mentioned which is related to react, here are also two issues (this, this) related to documentation.
Also, one thing I missed about
useTransitiondocs, is whether I should use singleuseTransitionfor multiple actions, or should each action have its ownuseTransition? Would be nice if docs discussed that. Don't you think?but should not that info be in the docs?
Yeah, we should update it to say the
actionprop follows the action prop pattern and link to those docs.which might lead someone think that formAction is not wrapped in a transition, due to the explicit startTransition in the end.
Fair, if you're not familiar with the action prop pattern. But also, the useOptimistic there should signal that it's inside a transition.
Also, one thing I missed about useTransition docs, is whether I should use single useTransition for multiple actions, or should each action have its own useTransition?
Depends on the use case?
But also, the useOptimistic there should signal that it's inside a transition.
Could you elaborate this a bit? You mean since
formActionusesaddOptimisticMessageinside it meansformActionis wrapped in transition automatically? Docs don't say this either, if that's the case.Depends on the use case?
You probably mean that depending on the use case, one should use either single
useTransitionor multiple for different actions. But that was my point. In order to make that decision, someone must be aware of the implications of using singleuseTransitionvs multiple, no?No, not automatically. But if you're assuming it's not in a transition because it contains another
startTransition(not sure why you would assume this since it's a very common thing to do), why wouldn't you see theuseOptimisticfirst and assume it's in a transition, since useOptimistic doesn't really do anything outside of startTransition. Doesn't matter though, either way we should update it.I really don't understand the multiple useTransition hooks thing. Can you provide a codesandbox where it's not clear if the code should use one
useTransitionhook or multiple?No, not automatically. But if you're assuming it's not in a transition because it contains another startTransition (not sure why you would assume this since it's a very common thing to do), why wouldn't you see the useOptimistic first and assume it's in a transition, since useOptimistic doesn't really do anything outside of startTransition. Doesn't matter though, either way we should update it.
You are saying react expects
updateFnofuseOptimisticto be in a transition. Right? Ok, but again,useOptimisticdocs don't say that. That's why I would not have thought that what you said.I really don't understand the multiple useTransition hooks thing. Can you provide a codesandbox where it's not clear if the code should use one useTransition hook or multiple?
Let's take this example:
import React, { useState, useTransition } from "react"; function MyComponent() { const [isPending, startTransition] = useTransition(); const [count, setCount] = useState(0); const [text, setText] = useState(""); function handleClick() { // Two separate actions: increment count, update text startTransition(() => { setCount(c => c + 1); }); startTransition(() => { setText("Clicked!"); }); } return ( <div> <p>Count: {count}</p> <p>Text: {text}</p> <button onClick={handleClick}>Click me</button> {isPending && <p>Updating…</p>} </div> ); }Here we use one
useTransitionhook for two separate actions insidehandleClickYou could also do this:
const [isPendingCount, startCountTransition] = useTransition(); const [isPendingText, startTextTransition] = useTransition();And wrap each state update in its own transition.
So the question becomes: is it better to share one transition or create multiple ones? Like what are the differences?Did you run that code? It has the same result. Is there an example where having different actions result in different UIs?
I would like to make one side remark if you allow me. IMHO when someone is receiving feedback, they should try to find some truth in it, not disregard it if they don't agree fully.
Did you run that code? It has the same result. Is there an example where having different actions result in different UIs?
Of course they might have the same result. But often that is not the whole story right?
Here:
let [x, setX] = React.useState(0);
setX(x+1)andsetX(ps=>ps+1)most of the time also have the same result, but it does not mean they are the same, right?For this example, that is the whole story though? They would never be different? In either case, the
isPendingflags are immediately rendered withtrue, and then there is a transition to render both state updates together. The only way they could be separate is if you triggered them from different events/buttons, and in which case it seems obvious when you would want them to have separate pending flags or the same flag, isn't it?I'm not asking questions to be argumentative, I'm trying to understand what the root of the question is so I can see how we would document it. The suggestion really just doesn't make sense to me without an example of what you mean, so I think there's either a break down in your understanding of transitions which more docs can help with, or a break down in my understanding of the suggestion.
Fixed the docs issue, thanks for the suggestion!
We can continue the question about when to use multiple
useTransitionhooks here or in a new issue!We can continue the question about when to use multiple useTransition hooks here or in a new issue!
Check here, even the
useEffectdocs have some advice on whether you should use one effect or multiple for different actions. That's what I meant.For transitions, that would mean addressing things like, what are the differences of using one
useTransitionvs multiple. One is with the former approach all those actions would share single pending state. Right? Are there maybe other differences in terms of behavior?The only way they could be separate is if you triggered them from different events/buttons, and in which case it seems obvious when you would want them to have separate pending flags or the same flag, isn't it?
Maybe it is not so obvious. I haven't used that hook extensively though. So I remember having questions I mentioned above when I was skimming through the docs.
So if you say that there really is no difference between those two approaches, except in the case when there is one
useTransitionthere is a shared pending state - then fine, maybe there isn't too much to add in the docs. But if there is more to it, it should be in docs. Like I showed before, remember evenuseEffecthas similar section, so that's why I was thinking maybe there was more to it.
Just a minor aside remark, here:
<Item key={item.id} onClick={() => handleClick(item)} />if we pass the arrow function to
onClickprops that way, then that defeats the purpose of usinguseCallbackonhandleClickno?
Also your pull request is a good addition to the docs but does it really close the current issue? Current issue was just asking to make clear whether server functions should be wrapped in transitions or not in general.
Ah yeah I can see what you mean based on the effect example, but for transitions that would be "each useTransition gets it's own isPending state". Other than that, yeah it's the same currently. In the future, separate hooks may trigger independent transitions, but there's already a caveat listed on the page for that.
I think what's really missing that goes to the spirit of what you're asking is Learn docs for Transitions (like the effect link). That's a huge gap we need to address.
@gmoniava thanks for flagging, here's the fix for the compiler docs: #7967
Current issue was just asking to make clear whether server functions should be wrapped in transitions or not in general.
Server Functions don't need to be wrapped in a transition, but they commonly are. The docs specific for Server Functions are not on the
<form>page, they're on the Server Function page, which includes examples with and without transitions/actions: https://react.dev/reference/rsc/server-functionsFYI someone also confirmed they experienced the bug I mentioned above.
Summary
Here it says:
Which seems to suggest we should always wrap server functions in transitions when using them outside forms.
However here is example from docs without wrapping them in transitions:
Can docs make it clearer which to use?
Page
https://react.dev/reference/rsc/use-server#calling-a-server-function-outside-of-form
https://react.dev/reference/rsc/server-functions#creating-a-server-function-from-a-server-component
Suggestion
It should be made more clear whether both approaches are allowed or not and if allowed, what are pros cons of each.
PS. Initially I had opened this issue as typo/mistake but I guess Suggestion is a better fit, changed title, but old label remains.