Skip to main content

Command Palette

Search for a command to run...

13) useReducer Hook

Updated
View as Markdown
  1. Concept of useReducer
    The useReducer hook in React is a state management hook used when your component’s state logic becomes complex — especially when the state transitions depend on actions, or when multiple pieces of state update together.
    It works similar to a Redux-like reducer pattern: You have state, You have actions and A reducer function decides how the state changes based on the action.

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

    Parameters -
    i) reducer - A function (state, action) => newState
    ii) initialState - The starting state value
    Return Values -
    iii) state - The current state
    iv) dispatch - A function used to send actions to the reducer

  2. Example of useReducer

    import React, { useReducer } from 'react';
    
    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;
       }
     };
    
    const getIncrementValue = () => {
       dispatch({ type: "increment" });
    }
    
    const getDecrementValue = () => {
       dispatch({ type: "decrement" });
    }
    
    function Counter() {
        const [state, dispatch] = useReducer(reducer, initialState);
    
        return (
          <div>
            <p>Count: {state.count}</p>
            <button onClick={getIncrementValue}>Increment</button>
            <button onClick={getDecrementValue}>Decrement</button>
          </div>
        );
    }
    
    export default Counter;
    
  3. When to Use useReducer
    i) State logic is complex
    Multiple sub-values and Next state depends on previous state
    ii) Multiple state updates must be grouped
    (e.g., forms, complex UI components)
    iii) State transitions follow a clear pattern
    e.g., loading → success → error
    iv) You want predictable, testable state updates
    v) You're lifting state or managing global-like state without adding Redux
    vi) When managing form submission.

  4. How useReducer Works
    i) You define a reducer
    A reducer is a pure function that receives the current state and the action
    And returns the next state

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

    ii) You initialize the state with useReducer
    React calls your reducer internally and gives you:
    state → the current state
    dispatch → a function for triggering actions

    const [state, dispatch] = useReducer(reducer, { count: 0 });
    

    iii) You trigger changes using dispatch
    When something happens (button click, input change, etc.),

    dispatch({ type: "increment" });
    

    iv) React calls the reducer and updates the UI
    After you dispatch an action,
    React calls your reducer(state, action) internally.
    Reducer returns a new updated state.
    React re-renders the component with that new state.
    This keeps state updates predictable & structured.

  5. Basic Interview Questions
    i) What is the useReducer hook in React?
    ii) How does useReducer differ from useState?
    iii) What is the syntax of the useReducer hook?
    iv) What are the parameters of useReducer?
    v) What does dispatch do in useReducer?
    vi) What is a reducer function?
    vii) What is the purpose of the action object in useReducer?
    viii) What does useReducer return?
    ix) When should you use useReducer over useState?
    x) Can you update multiple state values using one action in useReducer?

  6. Intermediate Interview Questions
    i) How does the reducer function maintain purity?
    ii) What happens if the reducer returns the same state?
    iii) How do you handle complex state updates using useReducer?
    iv) Can useReducer be used with useContext? How?
    v) How do you pass arguments to the dispatch function?
    vi) What is lazy initialization in useReducer?
    vii) How do you optimize performance in components using useReducer?
    viii) Can you explain the concept of action types and payloads?
    ix) Can you compare Redux reducers and React’s useReducer reducers?
    x) How do you structure reducers for readability?

  7. Advanced / Scenario-Based Questions
    i) When is useReducer NOT a good choice?
    ii) How do you split a large reducer into smaller reducers (like combineReducers)?
    iii) How do you handle asynchronous logic with useReducer?
    iv) How do you test a reducer function?
    v) How do you memoize a dispatch function or avoid unnecessary re-renders?vi) Can you implement a form state using useReducer?
    vii) What patterns do you follow to avoid deeply nested state updates?
    viii) How do you debug complex reducer-driven components?
    ix) How does React ensure the reducer is stable across renders?
    x) How would you manage side effects with useReducer? (e.g., using middleware-like patterns or hooks)

  8. Hands-On / Coding Interview Questions
    i) Implement a counter using useReducer.
    ii) Implement a todo list using useReducer.
    iii) Build a form with multiple fields using useReducer.
    iv) Show how to handle loading, success, and error states with useReducer.
    v) Refactor a component using many useState calls into one useReducer.
    vi) Write a reducer that updates nested properties safely.
    vii) Write an example using lazy initialization with useReducer.

  9. Tricky/Conceptual Questions
    i) Why must reducer functions be pure?
    ii) What happens if you mutate the state object inside the reducer?
    iii) Why should you never perform side effects inside the reducer?
    iv) Why is dispatch reference stable across renders?
    v) Can dispatch cause batching of updates? How?
    vi) How does React decide when to re-render components using useReducer?vii) Why shouldn’t reducers depend on props or external variables?
    viii) Can you share one reducer across multiple components?
    ix) What’s the difference between dispatching an action and calling a setter?
    x) How do you prevent reducer inflation (too many action types)?