The Road to Next — your interactive course for Next.js with React

React Form Button

Robin Wieruch

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:

tsx
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:

tsx
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:

sh
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:

tsx
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!

Never Miss an Article

Join 50,000+ developers getting weekly insights on full-stack engineering and AI.

AI Agentic UI Architecture React Next.js TypeScript Node.js Full-Stack Monorepos Product Engineering
Subscribe on Substack

High signal, low noise. Unsubscribe at any time.