Skip to content

How to use useReducer in React

useReducer is a React Hook that provides an alternative to useState for managing complex state logic in your components. It’s particularly useful when:

Basic Syntax

const [state, dispatch] = useReducer(reducer, initialState);

Example: Counter

const initialState = { count: 0 };

const reducer = (state, action) => {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    case 'decrement':
      return { count: state.count - 1 };
    default:
      return state;
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);
  return (
    <div>
      Count: {state.count}
      <button onClick={() => dispatch({ type: 'increment' })}>+</button>
      <button onClick={() => dispatch({ type: 'decrement' })}>-</button>
    </div>
  );
}

Example 2: SignUp Form

import { useReducer } from 'react';

// Initial form state
const initialState = {
  name: '',
  email: '',
  subscribed: false,
};

const formReducer = (state, action) => {
  switch (action.type) {
    case 'UPDATE_FIELD':
      return {
        ...state,
        [action.field]: action.value,
      };
    case 'TOGGLE_SUBSCRIPTION':
      return {
        ...state,
        subscribed: !state.subscribed,
      };
    case 'RESET':
      return initialState;
    default:
      return state;
  }
}

export default function SignupForm() {
  const [state, dispatch] = useReducer(formReducer, initialState);

  const handleChange = (e) => {
    dispatch({
      type: 'UPDATE_FIELD',
      field: e.target.name,
      value: e.target.value,
    });
  };

  const handleSubmit = (e) => {
    e.preventDefault();
    console.log('Form submitted:', state);
    dispatch({ type: 'RESET' });
  };

  return (
    <form onSubmit={handleSubmit}>
      <label>
        Name:
        <input name="name" value={state.name} onChange={handleChange} />
      </label>

      <label>
        Email:
        <input name="email" value={state.email} onChange={handleChange} />
      </label>

      <label>
        <input
          type="checkbox"
          checked={state.subscribed}
          onChange={() => dispatch({ type: 'TOGGLE_SUBSCRIPTION' })}
        />
        Subscribe to newsletter
      </label>

      <button type="submit">Submit</button>
    </form>
  );
}

Summary

References