ReactJS - useFormState() Hook



useFormState is a useful tool for React websites. When we want to update something on a webpage based on what happens when we fill out a form, we use it. For example, we might want to increase a number when we click a button in a form.

Syntax

useFormState(func, initialState)

Parameters

func − When the form is submitted or a button is pressed, the function fn is called. When we call the function, it will receive the previous state of the form (first the initialState that we pass, then its previous return value) as its first parameter, followed by the arguments that a form action usually receives.

initialState − The value of the state at the start. Any serializable value can be used. After the action is invoked for the first time, this argument is ignored.

Return Value

useFormState generates an array having only two values −

  • The current state. It will match the initialState we passed during the first render. It will match the value returned by the action when it is invoked.

  • A new action that we can send to our form component as the action prop or formAction prop to any button component within the form.

Examples

Example − Counter Increment Decrement App

At the top level of the component, useFormState to set up the component state that is updated when a form action is executed. We provide an existing form action function and an initial state to useFormState, and it returns a new action and the most recent form state. The most recent form state is also sent to the function we specified.

In this new example, we will use useFormState to create a basic counter that decrements when the "Decrement" button is pressed.

import { useFormState } from "react-dom";

async function increment(previousState, formData) {
   return previousState + 1;
}

async function decrement(previousState, formData) {
   return previousState - 1;
}

export default function App({}) {
   const [state, incrementAction] = useFormState(increment, 0);
   const [state2, decrementAction] = useFormState(decrement, 0);
   
   return (
      <div>
         <form>
            <p>Counter: {state}</p>
            <button formAction={incrementAction}>Increment</button>
            <button formAction={decrementAction}>Decrement</button>
         </form>
      </div>
   );
}

Output

counter2

Example

In this example, we are going to make an app that allows users to submit product feedback. To manage the feedback form and show a message based on the user's input, we will use useFormState. The code is as follows −

actions.js

"use server";

export async function submitFeedback(prevState, queryData) {
   const feedback = queryData.get("feedback");
   if (feedback) {
      return "Thanks for your feedback!";
   } else {
      return "Please provide your feedback before submitting.";
   }
}

App.js

import { useFormState } from "react-dom";
import { submitFeedback } from "./actions.js";

function FeedbackForm() {
   const [message, formAction] = useFormState(submitFeedback, null);
   
   return (
      <form action={formAction}>
         <h2>Product Feedback</h2>
         <label>
            Your Feedback:
            <textarea name="feedback" />
         </label>
         <button type="submit">Submit Feedback</button>
         {message}
      </form>
   );
}

export default function App() {
   return (
      <div>
         <FeedbackForm />
      </div>
   );
}

Output

product feedback

In the above example, we have a FeedbackForm component that allows users to offer product feedback. It displays a message based on whether or not the user supplied feedback using the submitFeedback action from actions.js. The feedback form is rendered by the App component. Depending on the requirement, we can create multiple instances of the FeedbackForm component.

Example

So let us see one more example using the useFormState function. In this app we will create a simple online store where we can add items to our shopping cart. In the main component 'AddToCartForm' we have two properties: itemID and itemTitle, representing the unique ID and title of an item. Inside AddToCartForm, there is a form with a hidden input for the item ID and a button to add the item to the cart. The form uses the useFormState hook from the react-dom library. So the app uses a simple server-side setup in the actions.js file.

import { useState } from "react";
import { useFormState } from "react-dom";
import { addToCart } from "./actions.js";

function AddToCartForm({itemID, itemTitle}) {
   const [message, formAction] = useFormState(addToCart, null);
   return (
      <form action={formAction}>
         <h2>{itemTitle}</h2>
         <input type="hidden" name="itemID" value={itemID} />
         <button type="submit">Add to Cart</button>
         {message}
      </form>
   );
}

export default function App() {
   return (
      <>
         <AddToCartForm itemID="1" itemTitle="Dynamic Programming: Models and App" />
         <AddToCartForm itemID="2" itemTitle="Soft Computing Techniques for Engineering Optimization" />
      </>
   )
}

actions.js

"use server";

export async function addToCart(prevState, queryData) {
   const itemID = queryData.get('itemID');
   if (itemID === "1") {
      return "Added to cart";
   } else {
      return "Couldn't add to cart: the item is sold out.";
   }
}

Output

dynamic programming

Overall, this app shows a basic form handling mechanism in React for adding items to a shopping cart.

Limitations

  • UseFormState, when used with a framework that supports React Server Components, allows us to make forms interactive before JavaScript is executed on the client. It is similar to component local state when used without Server Components.

  • As its first parameter, the function given to useFormState receives an extra argument, the previous or starting state. This changes the signature from what it would be if it were used straight as a form action without using useFormState.

Summary

The useFormState function helps us to set up and manage the behavior of forms within our components. We provide it with a specified action function and an initial state, and it returns the current form state and a new action that can be used to initiate form updates.

reactjs_reference_api.htm
Advertisements