Next.js Discord

Discord Forum

Is it Ok to use Server actions like that?

Answered
rphlmr 🫡 posted this in #help-forum
Open in Discord
It works very well but I wonder if there is any drawback.

I use startTransition to use that outside of forms.

//page.tsx
"use client";

import { submitUsername } from "./action";
import { useAction } from "./use-action";

export default function Playground() {
    const { response, action, isPending } = useAction(submitUsername);

    return (
        <main className="flex min-h-screen flex-col items-center gap-y-10 p-24">
            <form action={action}>
                <input name="username" />
                &nbsp;
                <button type="submit">Submit</button>
            </form>
            {isPending && <p className="text-blue-500">Loading</p>}
            {!isPending && response?.error && (
                <p className="text-red-500">{response.error}</p>
            )}
            {!isPending && response?.success && (
                <p className="text-green-500">Success!</p>
            )}
        </main>
    );
}


// use-action.ts
import { useState, useTransition } from "react";

export function useAction<T>(action: (formData: FormData) => Promise<T>) {
    const [isPending, startTransition] = useTransition();
    const [response, setResponse] = useState<T | undefined>(undefined);

    return {
        response,
        isPending,
        action: async (formData: FormData) => {
            startTransition(async () => {
                const response = await action(formData);
                setResponse(response);
            });
        },
    };
}


// action.ts
"use server";

export async function submitUsername(formData: FormData) {
    const username = String(formData.get("username"));

    // fake latency
    await new Promise((resolve) => setTimeout(resolve, 1000));

    if (!username) {
        return { error: "Please enter a username." };
    }

    return { success: true };
}
Answered by joulev
i think it's good, i don't see any drawbacks either
View full answer

21 Replies

i think it's good, i don't see any drawbacks either
Answer
Trying to wrap my head around transitions: what's the benefit here instead of using a loading state?
example from the official doc mainly mentions slow renders, but it's not really the case here
is it more a good practice as you may have multiple components doing their things, so transitions let you cancel those actions say on page change ?
"The function you pass to startTransition must be synchronous. React immediately executes this function, marking all state updates that happen while it executes as transitions. If you try to perform more state updates later (for example, in a timeout), they won’t be marked as transitions." also this is not clear to me given that you use async/await
Sorry I kinda hijack your question with more questions but I think it's helpful to understand the best approach here ^^
@Eric Burel Trying to wrap my head around transitions: what's the benefit here instead of using a loading state?
From Nextjs docs:
You can also invoke Server Actions by using startTransition if you want to use Server Actions outside of forms, buttons, or inputs.
https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions#custom-invocation-using-starttransition
But using useTransition disables progressive enhancement, so wouldnt say its the best practice either
Yeah they don't really explain why they need that though
but say that this is needed for server actions that do some mutations, in Next.js meaning, so redirect or data revalidation
a generic useAction is therefore maybe not suited, because it cannot do this distinction
doc is not very clear but it seems that useFormStatus should be prefered if the action is meant to be used in a form
it would be interesting to crack it open to see what it does, perhaps it's actually a transition under the hood
actually useFormStatus is from react -dom not next
useTransition gives us the isPending for free, this is one reason I use it here. And like discodian said, to also use this hook outside of a form
I should test what happen if I redirect in the function I pass to the hook 🧐 It works
@Eric Burel actually useFormStatus is from react -dom not next
I don't remember if it works with useTransition. I think not because useTransition rely on native form submission, and useTransition disable progressive enhancement. (Not sure at 💯)
@Eric Burel but say that this is needed for server actions that do some mutations, in Next.js meaning, so redirect or data revalidation
using redirect in the function passed to 'useAction' works 🔥.
The hook signature will say that there is no response.
ah yeah the generic is cool