Logo
Published on

Next.js Server Actions Are Super Awesome

Authors

Next.js has been changing frequently

I've been using Next.js for over three years now.

In those 3 years, the framework has definitely changed a lot. Sometimes for the better, and sometimes, not so much.

IMO, the biggest changes came along with Next 14 where Next has started to work more like a PHP framework (I think so).

Since then, I've started using server pages where ever possible. I love the instant data fetching/updating capabilities that server side pages have. It was an amazing experience to use Server Actions (they're quite simple).

I'll try to explain how to do that in a short way.

Suppose you had a file named actions.ts where you were exporting a function that does some data mutation in your database:

lib/actions.ts
'use server'
export function addData({name, email}: {name: string, email: string}) {
    ...
    const {data, error} = await supabase
    .from('user')
    .insert({
        name: name,
        email: email,
    })
    ...
}

You would need to import this function in your file that has the form and bind the action to the form, just like you would without react.

form/page.tsx
import addData from '@/lib/actions.ts'
export default function FormPage() {
    return (
        <div>
            <form action={addData}>
                <input name="email" />
                <input name="name" />
                <button>Submit User</button>
            </form>
        </div>
    )
}

There's a whole bunch of ways you can make server actions work for you.

Next.js has a great documentation for this. Please check it out if you want to learn how else you can use Server Actions.

There's one thing that's not discussed in the documentation that I'd like to explain here.

Client Side forms can not send anything else other than simple json

I was stuck at this problem for a while.

I wanted to send a profile image and I was using useState in that component to get input from the form.

This backfired as I found out if there's a file with a 'use client' directive at the top, it can only send simple json to the server based file (node instance).

I would recommend that if you have files to mutate in addition to strings (text), you should use a server side form instead, or send the data to the database using an async function.

Using useEffect to fetch data

I try to avoid using useEffects as much as I can, but it was necessary when I was fetching data before Next 14.

With server side code, I can get my data in the server side pages, and pass it down as props in my UI components (client components) without the need for too many loading states. The data fetches before the page is rendered so the page/data loads pretty much instantly.

Here's what I ususally do:

dashboard/page.tsx
import readData from '@/lib/actions.ts'
import PrefilledForm from '@/ui/forms.tsx'

export default function Page() {
const data = await getData({ uid: uid.id });

return (
    <div className="flex h-screen">
        <nav className="md:block hidden">
            <SidebarComponent />
        </nav>
        <div className="flex-grow p-11">
            <h1 className="text-2xl">Prefilled Form</h1>
            <PrefilledForm
                uid={data?.user?.id}
                field_1={data.question_1}
                field_2={data.question_2}
            />
        </div>
    </div>
    );
}

I think everyone should start using server actions.

They're super cool and simple to work with once you get a hang of it.