Skip to content

[Suggestion]: Should server functions be wrapped in transitions? (conflicting info in the docs) #7734

Description

@gmoniava

Summary

Here it says:

When using a Server Function outside a form, call the Server Function in a Transition, which allows you to display a loading indicator, show optimistic state updates, and handle unexpected errors

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:

// Server Component
import Button from './Button';

function EmptyNote () {
  async function createNoteAction() {
    // Server Function
    'use server';
    
    await db.notes.create();
  }

  return <Button onClick={createNoteAction}/>;
}
// Client 
"use client";

export default function Button({onClick}) { 
  console.log(onClick); 
  // {$$typeof: Symbol.for("react.server.reference"), $$id: 'createNoteAction'}
  return <button onClick={() => onClick()}>Create Empty Note</button>
}

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.

Activity

  1. 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
  2. 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
  3. gmoniava commented on Jul 12, 2025

    @gmoniava
    Author

    @poteto Sorry for direct tag - but would be nice if someone can have a look

  4. rickhanlonii commented on Aug 28, 2025

    @rickhanlonii
    Member

    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>
    • Update the example here to do something different, like logging that doesn't need UI (as well as the one after it).
  5. gmoniava commented on Aug 28, 2025

    @gmoniava
    Author

    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 action prop of a form, is this function automatically wrapped in transition during submit? I think that happens when you use useActionState, 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.

  6. rickhanlonii commented on Sep 2, 2025

    @rickhanlonii
    Member

    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 form is called action so it's implemented using the action prop 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.

  7. gmoniava commented on Sep 2, 2025

    @gmoniava
    Author

    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 formAction is not wrapped in a transition, due to the explicit startTransition in 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 useTransition docs, is whether I should use single useTransition for multiple actions, or should each action have its own useTransition? Would be nice if docs discussed that. Don't you think?

  8. rickhanlonii commented on Sep 2, 2025

    @rickhanlonii
    Member

    but should not that info be in the docs?

    Yeah, we should update it to say the action prop 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?

  9. gmoniava commented on Sep 2, 2025

    @gmoniava
    Author

    But also, the useOptimistic there should signal that it's inside a transition.

    Could you elaborate this a bit? You mean since formAction uses addOptimisticMessage inside it means formAction is 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 useTransition or multiple for different actions. But that was my point. In order to make that decision, someone must be aware of the implications of using single useTransition vs multiple, no?

  10. rickhanlonii commented on Sep 2, 2025

    @rickhanlonii
    Member

    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.

    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?

  11. gmoniava commented on Sep 2, 2025

    @gmoniava
    Author

    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 updateFn of useOptimistic to be in a transition. Right? Ok, but again, useOptimistic docs 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 useTransition hook for two separate actions inside handleClick

    You 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?

  12. rickhanlonii commented on Sep 2, 2025

    @rickhanlonii
    Member

    Did you run that code? It has the same result. Is there an example where having different actions result in different UIs?

  13. gmoniava commented on Sep 2, 2025

    @gmoniava
    Author

    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) and setX(ps=>ps+1) most of the time also have the same result, but it does not mean they are the same, right?

    @rickhanlonii

  14. rickhanlonii commented on Sep 2, 2025

    @rickhanlonii
    Member

    For this example, that is the whole story though? They would never be different? In either case, the isPending flags are immediately rendered with true, 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.

  15. rickhanlonii commented on Sep 2, 2025

    @rickhanlonii
    Member

    Fixed the docs issue, thanks for the suggestion!

    We can continue the question about when to use multiple useTransition hooks here or in a new issue!

  16. gmoniava commented on Sep 3, 2025

    @gmoniava
    Author

    We can continue the question about when to use multiple useTransition hooks here or in a new issue!

    Check here, even the useEffect docs 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 useTransition vs 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 useTransition there 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 even useEffect has 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 onClick props that way, then that defeats the purpose of using useCallback on handleClick no?


    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.

    @rickhanlonii

  17. rickhanlonii commented on Sep 3, 2025

    @rickhanlonii
    Member

    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.

  18. rickhanlonii commented on Sep 3, 2025

    @rickhanlonii
    Member

    @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-functions

  19. gmoniava commented on Sep 3, 2025

    @gmoniava
    Author

    FYI someone also confirmed they experienced the bug I mentioned above.

    @rickhanlonii

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions