Nader's Daily Blog
Welcome to Every Developers favorite blog in the Devosphere

New product features | The latest in technology | The weekly debugging nightmares & more!

Next js 13 server actions introduction

Next js 13 server actions introduction

July 25, 2023

Nader Elmahdy

Nader Elmahdy

Take my knowledge and shove it up your brain...

Who needs api endpoints when we have server actions ?

Next js

Next js 13 introduced a new experimental feature that makes it so much easier to connect with your database and fetch/update data without creating an API endpoint.

So basically the API endpoint will be replaced by a function.


Example:

Here, I'm using Prisma to connect to my DB, but this applies to any other method.

lib/products.ts

1import { prisma } from "./prisma";
2
3export async function getProducts() {
4  try {
5    const products = await prisma.product.findMany({});
6    return { products };
7  } catch (error) {
8    return { error };
9  }
10}

In the above example, I created a function that returns all the products in my database, to use it, I simply need to import it in my page and call it.

page.tsx

1import { getProducts } from "@/lib/products";
2
3async function page() {
4  const { products } = await getProducts();
5  return <div>page</div>;
6}
7
8export default page;
9

And just like that, I have my data in a variable that I can map over and display.

Using server actions in client components

These functions will work just fine in server components, but if you try to use them inside client components, you'll face a similar error:



To fix that, you'll need to create a file called _actions.ts inside your app folder.

We'll mark this "use server" to make sure all the functions in that file run on the server.

Now let's say that I created a function that adds a new product to my database.

lib/products.ts

1export async function createProduct(
2  Title: string,
3  Price: number,
4  Images: Array<object>,
5  mainImg: string,
6  Description: string,
7  Colors: Array<string>,
8  Properties: object
9) {
10  try {
11    const product = await prisma.product.create({
12      data: {
13        Title,
14        Price,
15        Images,
16        Description,
17        mainImg,
18        Colors,
19        Properties,
20      },
21    });
22    return { product };
23  } catch (error) {
24    return { error };
25  }
26}

Typically you'd need to use this function in a client component (upload form), but you can't just import it and use it as you'd get the above error.

You'll need to go to the _actions.ts file that we just created and import that function:

_actions.ts

1"use server";
2import {createProduct} from "@/lib/products";




Next, you'll need to create a function that calls this function.

_actions.ts

1"use server";
2import {createProduct} from "@/lib/products";
3
4export async function createProductAction(
5  Title: string,
6  price: number,
7  Images: Array<object>,
8  mainImg: string,
9  Description: string,
10  Categories: Array<string>,
11  Colors: Array<string>,
12) {
13  await createProduct(
14    Title,
15    price,
16    Images,
17    mainImg,
18    Description,
19    Colors,
20    Categories,
21  );
22}


Now the createProductAction function can be called in client components and it will work just fine, the same applies for updating and deleting.

Note: You can't use the getProducts function in client components, even if you create a function for in the _actions.ts file, it won't work.

You can create, update , and delete, but you can't get in client components.

And that's basically all you need to know about server actions, I used Prisma, but you can use any other method to connect to your database.

You might also like: