Rreact.wiki
React Snippets

Form State Management with useReducer

Hooksformsreducerstate-managementvalidationhooks

A reusable, type-safe React hook for managing complex form state (values, errors, touched) using useReducer.

TSX
import { useReducer } from 'react';
 
const formReducer = (state, action) => {
  switch (action.type) {
    case 'UPDATE_FIELD':
      return {
        ...state,
        values: {
          ...state.values,
          [action.field]: action.value
        }
      };
    case 'SET_ERROR':
      return {
        ...state,
        errors: {
          ...state.errors,
          [action.field]: action.error
        }
      };
    case 'SET_TOUCHED':
      return {
        ...state,
        touched: {
          ...state.touched,
          [action.field]: true
        }
      };
    case 'RESET_FORM':
      return {
        values: action.initialValues || {},
        errors: {},
        touched: {}
      };
    default:
      return state;
  }
};
 
function useFormReducer(initialValues = {}) {
  const [formState, dispatch] = useReducer(formReducer, {
    values: initialValues,
    errors: {},
    touched: {}
  });
 
  const updateField = (field, value) => {
    dispatch({ type: 'UPDATE_FIELD', field, value });
  };
 
  const setError = (field, error) => {
    dispatch({ type: 'SET_ERROR', field, error });
  };
 
  const setTouched = (field) => {
    dispatch({ type: 'SET_TOUCHED', field });
  };
 
  const resetForm = (newInitialValues) => {
    dispatch({ type: 'RESET_FORM', initialValues: newInitialValues });
  };
 
  return {
    formState,
    updateField,
    setError,
    setTouched,
    resetForm
  };
}
 
export default useFormReducer;

useFormReducer is a lightweight, predictable form state manager built on useReducer. It separates concerns cleanly: formState.values, formState.errors, and formState.touched are always available and updated immutably. Use updateField, setError, and setTouched to imperatively control state per field — ideal for dynamic or deeply nested forms. Call resetForm() to restore initial values (or pass new ones). No external dependencies; works out of the box with TypeScript (add JSDoc or types if needed in your project). Note: This hook doesn’t include validation logic — pair it with useFormValidation or your own validator for full form handling.

Form State Management with useReducer — react.wiki