Code Premix

Form Validation in React Using the useReducer Hook

📅May 19, 2024
🗁React

Handling form validation in React can be a bit tricky, but with the useReducer hook, it becomes much more manageable and elegant. In this post, we’ll explore how to use useReducer to handle form state and validation, making your forms robust and easy to maintain.

What is useReducer?

The useReducer hook is a React hook that is used for state management. It’s an alternative to useState and is usually preferred when you have complex state logic that involves multiple sub-values or when the next state depends on the previous one.

Setting Up the Reducer

First, we need to set up our reducer. A reducer is a function that takes the current state and an action, then returns a new state.

const formReducer = (state, action) => {
  switch (action.type) {
    case 'INPUT_CHANGE':
      return {
        ...state,
        [action.field]: action.value,
        errors: {
          ...state.errors,
          [action.field]: action.error,
        },
      };
    case 'SUBMIT':
      const errors = validate(state);
      return { ...state, errors };
    default:
      return state;
  }
};

Initial State and Validation Function

Let’s define our initial state and a simple validation function.

const initialState = {
  username: '',
  email: '',
  errors: {},
};

const validate = (state) => {
  const errors = {};
  if (!state.username) errors.username = 'Username is required';
  if (!state.email) errors.email = 'Email is required';
  return errors;
};

Implementing the useReducer Hook

Now, let’s implement the useReducer hook in our form component.

const FormWithReducer = () => {
  const [state, dispatch] = useReducer(formReducer, initialState);

  const handleChange = (e) => {
    const { name, value } = e.target;
    dispatch({
      type: 'INPUT_CHANGE',
      field: name,
      value,
      error: validate({ ...state, [name]: value })[name],
    });
  };

  const handleSubmit = (e) => {
    e.preventDefault();
    dispatch({ type: 'SUBMIT' });
    const errors = validate(state);
    if (Object.keys(errors).length === 0) {
      console.log('Form submitted successfully', state);
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <div>
        <label>Username:</label>
        <input
          type="text"
          name="username"
          value={state.username}
          onChange={handleChange}
        />
        {state.errors.username && <p>{state.errors.username}</p>}
      </div>
      <div>
        <label>Email:</label>
        <input
          type="email"
          name="email"
          value={state.email}
          onChange={handleChange}
        />
        {state.errors.email && <p>{state.errors.email}</p>}
      </div>
      <button type="submit">Submit</button>
    </form>
  );
};

Conclusion

Using the useReducer hook for form validation in React helps in managing complex form state logic more effectively. It allows you to handle form data and validation in a cleaner and more structured way. Give it a try in your next React project!