How to Manage Forms with useState and useReducer

March 29, 2019

React Hooks have been out for a couple of months now, and developers are already seeing how they simplify state management in functional components. One common use case for state is handling form inputs, which traditionally required a lot of boilerplate code in class components.

With useState and useReducer, we can now manage form state in a much cleaner way. In this post, we’ll explore:

  • Controlled vs. uncontrolled components in forms
  • When to use useState vs. useReducer
  • How to manage complex forms efficiently

Controlled vs. Uncontrolled Components

In React, form elements can be controlled or uncontrolled:

  • Controlled components – React fully manages the input’s state via useState (or useReducer).
  • Uncontrolled components – The input’s state is handled by the DOM itself, accessed via ref.

In most cases, controlled components are the preferred approach because they allow React to manage form state predictably.

Example: Controlled Component with useState

Before Hooks, we used this.state to track form input values in class components:

class Form extends React.Component {
  constructor(props) {
    super(props);
    this.state = { name: "" };
  }

  handleChange = (event) => {
    this.setState({ name: event.target.value });
  };

  render() {
    return (
      <input
        type="text"
        value={this.state.name}
        onChange={this.handleChange}
      />
    );
  }
}

Now, with Hooks, we can use useState to manage form inputs in a much cleaner way:

import React, { useState } from "react";

function Form() {
  const [name, setName] = useState("");

  return (
    <input
      type="text"
      value={name}
      onChange={(e) => setName(e.target.value)}
    />
  );
}

Why is this better?

  • No need for a class or constructor.
  • No need to bind this.
  • Code is shorter and easier to read.

Using useReducer for Complex Forms

For simple forms, useState works fine. But what if you have multiple fields or need more advanced state logic (e.g., resetting, validation, handling multiple actions)? This is where useReducer shines.

Example: Managing a Multi-Field Form with useReducer

Instead of managing multiple useState calls, we can use useReducer to centralize state updates.

Step 1: Define the Reducer Function

function formReducer(state, action) {
  switch (action.type) {
    case "CHANGE":
      return { ...state, [action.field]: action.value };
    case "RESET":
      return { name: "", email: "" };
    default:
      return state;
  }
}

Step 2: Use useReducer in the Component

import React, { useReducer } from "react";

function Form() {
  const [state, dispatch] = useReducer(formReducer, { name: "", email: "" });

  return (
    <form>
      <input
        type="text"
        value={state.name}
        onChange={(e) =>
          dispatch({ type: "CHANGE", field: "name", value: e.target.value })
        }
      />
      <input
        type="email"
        value={state.email}
        onChange={(e) =>
          dispatch({ type: "CHANGE", field: "email", value: e.target.value })
        }
      />
      <button type="button" onClick={() => dispatch({ type: "RESET" })}>
        Reset
      </button>
    </form>
  );
}

Why useReducer?

  • Centralized state logic – Instead of multiple useState calls, all updates go through the reducer.
  • Scalability – Adding new fields or actions is easy.
  • Cleaner code – Especially useful when handling complex form behavior.

When to Use useState vs. useReducer?

ScenarioUse useStateUse useReducer
Simple forms with a few fields
Forms with multiple fields⚠️ (can get messy)
Complex validation and logic
Multiple state transitions (reset, conditional updates)

General rule: If your form is simple, stick with useState. If it gets more complex, switch to useReducer to keep things organized.


Conclusion

React Hooks have made form management in functional components much easier. While useState is great for simple forms, useReducer provides better control for handling more complex form logic.

If you’re new to Hooks, now is the perfect time to start integrating them into your workflow. With React moving towards a functional-first approach, mastering Hooks will be essential in 2019 and beyond.

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *