How to use Next.Js 14 Server Actions
Tags: nextjs, react, javascript, webdev
Published: 2024-01-10 08:59:14

Next.Js 14 has added a lot of cool features that make development so much easier like:
- App Router
- Server Actions
- Route Handlers
- Client and Server Components

In this article, we will be covering Server Actions.

## What are Server Actions

A Server Action is simply an asynchronous function that runs on the server whenever a form is submitted. It allows you to run the code directly on the server. This way, you don't have to make a separate backend or API and don't need to send requests to the API. You can communicate with a database directly in a Server Action. 

You can use it in both client and server components.

## Using Server Actions

### Using Server Actions in Server Components

Simply make an asynchronous function inside a server component. Add the **"use server"** directive inside the function (at the top). Then attach an **action** property to the form element. 

The Server Action receives a **formData** object as an argument that lets you access the values of the input fields. After this, you can perform validation and store information directly in a database. No need to create an API endpoint.

```javascript
// server component

export const Form = () => {
  const createPost = async (formData) => {
    "use server"
    const title = formData.get("title")
    const description = formData.get("description")

    // store the post in the database directly
  }

  return (
    <form action={createPost}>
      <input type="text" name="title" />
      <input type="text" name="description" />
      <button type="submit">Submit</button>
    </form>
  )
}
```

### Using Server Actions in Client Components

Since a client component is rendered on the client, you cannot create Server Actions in a client component. But what you can do is, you can create a new file and add the **use server** directive at the top of the file. Now any function you create inside of that file will be considered a Server Action. Then you can import those Server Actions into a client component.

```javascript
"use server"

export const createPost = async (formData) => {
  const title = formData.get("title")
  const description = formData.get("description")

  // store the post in the database directly
}
```

Now you can import this Server Action in a client component.

```javascript
// client component
"use client"

import { createPost } from './actions'

export const Form = () => {
  return (
    <form action={createPost}>
      <input type="text" name="title" />
      <input type="text" name="description" />
      <button type="submit">Submit</button>
    </form>
  )
}
```

### Showing a Loading State

Now you might be wondering, how can we show a loading state because the function is being executed on the server.

To do this you can create a separate client component for your button. Inside of this component, you can use the **useFormStatus** hook. It tells you whether the Server Action has finished executing or is still being executed.

**Note:** You can only use the **useFormStatus** hook inside of a form. That's why you have to create a separate component for your button and place it inside the form.

```javascript
"use client"

import { useFormStatus } from "react-dom"

export const Button = ({ children }) => {
  const { pending } = useFormStatus()

  return (
    <button type="submit" disabled={pending}>
      {children} {pending && "Loading..."}
    </button>
  )
}
```

Now we can use it inside the form.

```javascript
// client component
"use client"

import { createPost } from './actions'
import { Button } from './Button'

export const Form = () => {
  return (
    <form action={createPost}>
      <input type="text" name="title" />
      <input type="text" name="description" />
      <Button>Submit</Button>
    </form>
  )
}
```

### Handling Errors and Success State

Now to show errors and success messages to the user, we can make use of the **useFormState** hook. It accepts a **Server Action** and an **Initial State** as an argument. It returns the **New State** and **a copy of the Server action**.

```javascript
// client component
"use client"

import { createPost } from './actions'
import { Button } from './Button'
import { useFormState } from "react-dom"
import { useEffect } from 'react'

export const Form = () => {
  const [createPostState, createPostAction] = useFormState(createPost, {
    error: null,
    success: false
  })

  useEffect(() => {
    if (createPostState.success) {
      alert("Post created!")
    }

    if (createPostState.error) {
      alert(createPostState.error)
    }
  }, [createPostState])

  return (
    <form action={createPostAction}>
      <input type="text" name="title" />
      <input type="text" name="description" />
      <Button>Submit</Button>
    </form>
  )
}
```

When using the **useFormState** hook. Your Server Action will receive an extra argument **prevState**. So you can modify your server action like this:

```javascript
"use server"

export const createPost = async (prevState, formData) => {
  const title = formData.get("title")
  const description = formData.get("description")

  if (!title) {
    return { error: "Enter the title!", success: false }
  }

  if (!description) {
    return { error: "Enter the description!", success: false }
  }

  // store the post in the database directly
  return { error: null, success: true }
}
```

## Conclusion

Server Actions in Next.Js 14 is an amazing feature. It makes development faster since you don't need a separate backend or API. From creating Server Actions to using them in different scenarios, this guide has provided a comprehensive overview of using Next.Js 14 Server Actions. To learn more about Next.Js 14 and Server Actions, read their official documentation.

- [Next.Js 14 Documentation](https://nextjs.org/docs "Next.Js 14 Documentation")
- [Server Actions Documentation](https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations "Server Actions Documentation")

## [MyDevPage](https://mydevpa.ge/): Create a Portfolio Website Instantly

[MyDevPage](https://mydevpa.ge/) allows you to build a portfolio website in minutes. Focus on building great projects and enhancing your skills rather than wasting your time building a portfolio website from scratch or customizing expensive templates.  

MyDevPage handles everything:

- Portfolio Creation
- SEO
- Analytics
- Customization
- Custom Domain
- Contact Form

![MyDevPa.ge](//images.ctfassets.net/vlpuprt2y2ne/6oOJjFtSMHjgeoNhDW1IOm/4a4cb3c8f946e7e8056c8ee122c406a4/image.png)