React Form Button

 by Robin Wieruch
 - Edit this Post

Here you will learn how to use a form button in React to trigger a server action in a Server Component without any form fields or form data. This can be useful if you want to trigger a server action with a button click, but don't want to use a Client Component to assign a click event handler.

React Button in a Client Component

We will start with a React component that displays a post and a button to delete it. The PostItem component receives a post object as a prop and displays the post title and a delete button:

type Post = {
id: string;
title: string;
};
type PostItemProps = {
post: Post;
};
export const PostItem = ({ post }: PostItemProps) => {
return (
<div>
<span>{post.title}</span>
<button>Delete</button>
</div>
);
};

In a Client Component, you could attach a click handler to the button to call the server with an API request. In Next.js the API could be implemented with a Route Handler:

export const PostItem = ({ post }: PostItemProps) => {
const handleDelete = () => {
// logging in browser
console.log("TODO: Call API to delete post");
};
return (
<div>
<span>{post.title}</span>
<button onClick={handleDelete}>Delete</button>
</div>
);
};

However, in a Server Component, you cannot attach a click handler to the button like in the code above. You may get a similar error to the following:

Error: Event handlers cannot be passed to Client Component props.
If you need interactivity, consider converting part of this to a Client Component.

So you are free to transform a Server Component to a Client Component with a client directive (read: "use client";), but if you want to keep the component as a Server Component, you can also use a form button to trigger a server action without using a Client Component.

React Form Button in a Server Component

If you want to keep it as a Server Component, you can use a form button to trigger a server action which runs on the server-side. The form button will submit the form and trigger the server action without any form fields or form data. Here is how you can do it:

export const PostItem = ({ post }: PostItemProps) => {
const deletePost = async () => {
"use server";
// logging in terminal
console.log("TODO: delete post in DB");
};
return (
<div>
<span>{post.title}</span>
<form action={deletePost}>
<button type="submit">Delete</button>
</form>
</div>
);
};

Essentially you are just using a form without any form fields and only a submit button. For developers from the old days this may be obvious, but when you are only used to perform client-side interactions with React, using a form with just a button may be new to you, because you have been used to use a button with an onClick handler for a long time.

You can find the repository for this tutorial over here. If you want to go beyond this, check out "The Road to Next" and get on the waitlist!

Keep reading about 

A button may be the first interactive element that you are using in a React component. Therefore, this is a short React tutorial by example for beginners about creating a button in React, how to use…

In this short tutorial, you will learn how to pass extra arguments to server actions in React forms. We will start with the following React form component that updates a post: In the above code…

The Road to React

Learn React by building real world applications. No setup configuration. No tooling. Plain React in 200+ pages of learning material. Learn React like 50.000+ readers.

Get it on Amazon.