Back to posts
Leveraging Actions in React 19 for Enhanced Form Handling

Leveraging Actions in React 19 for Enhanced Form Handling

Vikas Yadav / August 10, 2024

Dive into the new actions hooks in React 19 to improve how we can write forms in React.

If you have used Next.js, you have probably heard of Server Actions as a new way to handle form submissions and data mutations in Next.js applications. Server Actions have both server-side and client-side aspects to them and Actions, the client-side APIs are landing in React 19! React Actions are not specific to Next.js or data fetching – they can be used with other server-side frameworks for any asynchronous operations.

In this post, we will elaborate on what React Actions are and how to use the new hooks like useActionState and useFormStatus to build form submission experiences the modern way.

Note: As of writing, React 19 has not been published and the API can be prone to updates, so you should always refer to the latest version of the documentation.

Actions in HTML forms

Before we dive deeper into React Actions, we should first understand the 'action' property in native HTML forms. Before JavaScript was introduced, the common way to send the data to the server was via the action attribute on forms.

When we define a form element, we can also set an action attribute to a URI which will be used as the endpoint to send the data to the server. The action attribute is often combined with method attribute which can be set to HTTP methods like GET or PUT.

<form action='/user' method='POST'>

  <input name='name' id='name' value='' />

  <div>

    <button type='submit'>Save</button>

  </div>

</form>

When a user clicks on the "Save" button, the browser will make a HTTP request to the /user endpoint using the specified HTTP method. This is a very powerful pattern that does not rely on JavaScript, however there are downsides of this approach:

  1. It results in a full-page refresh
  2. Form states like loading and error cannot bedisplayed

Form submissions in React

Submitting forms in React is straightforward. It can be done by utilizing the onSubmit prop and fetch API. We can show loading and error states through usage of the useState hook and onSubmit prop.

import { useState } from 'react'



export default function UserForm() {

  const [isPending, setIsPending] = useState(false)

  const [error, setError] = useState(null)



  const handleSubmit = async event => {

    event.preventDefault()

    const data = new FormData(event.target)



    try {

      setError(false)

      setIsPending(true)



      await fetch('/user', {

        method: 'POST',

        body: JSON.stringify(data)

      })

      event.target.reset()

    } catch (err) {

      setError(err.message)

    } finally {

      setIsPending(false)

    }

  }



  return (

    <form onSubmit={handleSubmit}>

      <input id='name' name='name' />

      {error && <p>{error}</p>}

      <button type='submit'>{isPending ? 'Saving...' : 'Save'}</button>

    </form>

  )

}

Client-side form submissions and updates offer several advantages, particularly in terms of user experience and performance:

  • Server requests made without a full-page refresh, which results in faster feedback.

  • Show different form states like loading and error – better user experience.

While client-side form submissions and updates provide numerous benefits, there are also potential problems and pitfalls that we should be aware of:

  • Need to remember to use event.preventDefault otherwise the browser will do a full page refresh on submission of the form.

  • Boilerplate code is required to manually manage the form state.
  • Requires JavaScript to run.