Skip to main content

πŸ“˜ React useReducer β€” Complete In-Depth Guide


1. Introduction

πŸ”Ή What is useReducer

useReducer is a React Hook used for managing complex state logic in a component. It is an alternative to useState, especially useful when:
  • State has multiple sub-values
  • State transitions depend on previous state
  • Logic is complex or reusable
It follows the Reducer pattern, inspired by functional programming and state management libraries like Redux.

πŸ”Ή Why it is important in React

  • Centralizes state logic in one place
  • Makes state transitions predictable
  • Improves readability for complex components
  • Encourages pure functions and better testability
  • Scales better than useState for non-trivial logic

πŸ”Ή When and why we use it

Use useReducer when:

βœ… Good use cases:

  • Complex state transitions
  • Multiple related state variables
  • Deeply nested updates
  • Business logic-heavy components
  • Form management (with multiple fields)
  • State depends heavily on previous state

❌ Avoid when:

  • State is simple (use useState)
  • No complex transitions or logic

2. Concepts / Internal Workings


πŸ”Ή Core Concepts

1. Reducer Function

A pure function that determines how state changes.
  • Receives current state
  • Receives an action
  • Returns new state (immutable update)

2. Action

An object describing what happened

3. Dispatch

A function used to trigger state changes

4. State

The current value managed by the reducer

πŸ”Ή How it works internally in React

  1. Component calls useReducer(reducer, initialState)
  2. React:
    • Stores state internally
    • Returns [state, dispatch]
  3. When dispatch(action) is called:
    • React calls reducer with (currentState, action)
    • Gets new state
    • Triggers re-render

βš™οΈ Key Internal Behavior

  • React uses reference comparison (Object.is) to detect changes
  • If reducer returns same object β†’ no re-render
  • If new object β†’ re-render occurs

πŸ”Ή Relationship with other React features

πŸ”Έ useState

  • useState is a simplified version of useReducer
  • Internally, React implements useState using a reducer-like pattern

πŸ”Έ useContext

  • Common pairing:
    • useReducer β†’ manages state
    • useContext β†’ shares state globally

πŸ”Έ React Rendering

  • Dispatch triggers a reconciliation cycle
  • React schedules updates efficiently (especially in concurrent mode)

πŸ”Έ Redux

  • useReducer is a local Redux-like pattern
  • No middleware, but same core idea

3. Syntax & Examples


πŸ”Ή Basic Syntax


πŸ”Ή Example 1: Counter


πŸ”Ή Example 2: Complex State Object


πŸ”Ή Example 3: Todo List


πŸ”Ή Example 4: Lazy Initialization

πŸ‘‰ Useful when initial state is expensive to compute

πŸ”Ή Example 5: useReducer + useContext


πŸ”Ή Mini Variations

Dispatch with payload


Multiple reducers (manual composition)


4. Edge Cases / Common Mistakes


πŸ”΄ 1. Mutating state directly

❌ Wrong:
βœ… Correct:
πŸ‘‰ Mutation prevents React from detecting changes

πŸ”΄ 2. Returning same reference

πŸ‘‰ No re-render occurs

πŸ”΄ 3. Missing default case

πŸ‘‰ Without this, unexpected bugs may occur

πŸ”΄ 4. Dispatch inside render

πŸ‘‰ Causes infinite re-renders

πŸ”΄ 5. Overusing useReducer

πŸ‘‰ Not every state needs reducer logic πŸ‘‰ Adds unnecessary complexity

πŸ”΄ 6. Deep nested updates

πŸ‘‰ Hard to maintain β†’ consider normalization

πŸ”΄ 7. Async logic inside reducer

❌ Avoid:
πŸ‘‰ Reducers must be pure functions

πŸ”΄ 8. Dispatch identity misunderstanding

  • dispatch is stable across renders
  • Safe to pass down without memoization

5. Best Practices


βœ… 1. Keep reducer pure

  • No side effects
  • No API calls
  • No randomness

βœ… 2. Use action constants

πŸ‘‰ Prevents typos and improves maintainability
  • One reducer per domain (user, cart, form)
  • Avoid giant reducers

βœ… 4. Use meaningful action names

❌ "SET" βœ… "SET_USER_NAME"

βœ… 5. Normalize complex state

Instead of deep nesting:

βœ… 6. Combine with useContext for global state

  • Lightweight alternative to Redux
  • Good for medium-sized apps

βœ… 7. Optimize re-renders

  • Avoid unnecessary object creation
  • Split reducers if needed

βœ… 8. Lazy initialization for heavy state


βœ… 9. Debugging strategy

  • Log actions inside reducer:
  • Track state transitions

βœ… 10. Testing reducers

  • Reducers are pure β†’ easy to test

🧠 Final Mental Model

Think of useReducer as:
β€œA state machine where actions describe events, and reducer defines how state evolves.”

🧠 Advanced useReducer β€” Senior-Level Conceptual Questions & Answers


1. How is useReducer fundamentally different from useState under the hood?

βœ… Answer

At a high level, both are similar β€” React internally models useState as a specialized reducer.

πŸ” Key Differences

βš™οΈ Internal Insight

React internally does something like:

🧠 WHY it matters

  • useReducer gives predictable state transitions
  • Better for debugging (action logs)
  • More scalable for complex logic

2. Why must a reducer be a pure function, and what breaks if it’s not?

βœ… Answer

Reducers must be pure because React relies on:
  • Deterministic state updates
  • Safe re-execution (especially in concurrent rendering)

❌ Problem with impure reducers

πŸ”₯ What breaks?

  • React may call reducer multiple times
  • Causes duplicate API calls
  • Leads to inconsistent UI

🧠 WHY

React may replay updates during rendering (Concurrent Mode)

3. How does React determine whether to re-render after dispatch?

βœ… Answer

React uses reference equality (Object.is).

πŸ”΄ Subtle Bug

πŸ‘‰ No re-render happens

🧠 WHY

React assumes:
  • Same reference = no change
  • New reference = update required

4. What are the trade-offs between useReducer and Redux?

βœ… Answer

πŸ” Comparison

🧠 When to choose

  • useReducer β†’ component-level or medium complexity
  • Redux β†’ large apps, cross-cutting concerns

🧠 WHY

Redux adds:
  • Middleware pipeline
  • Time-travel debugging
  • Predictable global architecture

5. Why is dispatch stable across renders, and why does that matter?

βœ… Answer

React guarantees that dispatch is referentially stable.

🧠 WHY

  • Avoid unnecessary re-renders in children
  • Safe to pass down without useCallback

πŸ”₯ Contrast


6. What happens if multiple dispatches occur synchronously?

βœ… Answer

React batches updates.

Result:

  • Reducer runs twice
  • Final state reflects both updates

🧠 WHY

React queues updates and processes them in order

7. How does lazy initialization in useReducer improve performance?

βœ… Answer

🧠 WHY

  • init runs only once
  • Avoids recomputation on every render

πŸ”₯ Use case


8. How would you structure reducers in a large-scale application?

βœ… Answer

πŸ”Ή Pattern: Reducer Composition

🧠 WHY

  • Separation of concerns
  • Maintainability
  • Scalable architecture

9. Why is putting async logic inside reducers an anti-pattern?

βœ… Answer

Reducers must be pure and synchronous.

❌ Bad

βœ… Correct

🧠 WHY

  • Async logic breaks predictability
  • Hard to test
  • Violates functional programming principles

10. How does useReducer behave in concurrent rendering?

βœ… Answer

React may:
  • Pause
  • Resume
  • Replay reducer calls

🧠 WHY

Concurrent rendering allows:
  • Interruptible updates
  • Better UX

⚠️ Implication

Reducers must be:
  • Pure
  • Idempotent

11. What are the pitfalls of deeply nested state in reducers?

βœ… Answer

πŸ”΄ Problems

  • Verbose
  • Error-prone
  • Hard to maintain

βœ… Solution

  • Normalize state
  • Split reducers

12. When does useReducer become an anti-pattern?

βœ… Answer

❌ Overuse scenarios

  • Simple boolean toggles
  • Independent state variables

🧠 WHY

  • Adds unnecessary abstraction
  • Reduces readability

13. How do you debug complex reducer logic?

βœ… Answer

πŸ”Ή Techniques

  1. Log actions
  1. Trace state transitions
  2. Use custom middleware-like wrappers

🧠 WHY

Reducers are deterministic β†’ easy to trace

14. How does useReducer interact with useContext in global state design?

βœ… Answer

πŸ”Ή Pattern

🧠 WHY

  • Avoid prop drilling
  • Share state globally

⚠️ Trade-off

  • All consumers re-render unless optimized

15. How can you prevent unnecessary re-renders when using useReducer + Context?

βœ… Answer

πŸ”Ή Techniques

  • Split contexts
  • Memoize selectors
  • Use libraries like Zustand/Recoil if needed

🧠 WHY

Context updates trigger all consumers

16. Why are action objects preferred over direct function calls?

βœ… Answer

🧠 WHY

  • Declarative
  • Serializable
  • Easier debugging
  • Enables logging/history

17. What happens if the reducer throws an error?

βœ… Answer

  • Component crashes
  • Error propagates to nearest error boundary

🧠 WHY

Reducers run during render phase

βœ… Solution

  • Validate inputs
  • Use error boundaries

18. How would you model a finite state machine using useReducer?

βœ… Answer

🧠 WHY

  • Explicit transitions
  • Prevent invalid states

πŸ”š Final Thought

At a senior level, useReducer is not just a hook β€” it’s:
A predictable state transition system that helps you model complex UI logic with clarity and control.

🧠 Advanced useReducer β€” Senior-Level MCQs


1. When will a component NOT re-render after a dispatch?

Question:
What happens after dispatch({ type: "increment" })?

Options:

A. Component re-renders with updated count B. Component does not re-render C. React throws an error D. Behavior is undefined

βœ… Correct Answer: B

πŸ’‘ Explanation:

React compares state using reference equality (Object.is). Since the same object reference is returned, React skips re-render.

❌ Why others are wrong:

  • A: Incorrect β€” mutation doesn’t trigger re-render
  • C: No runtime error
  • D: Behavior is deterministic

2. What happens if reducer returns a completely new object but with identical values?

Options:

A. No re-render B. Re-render occurs C. React shallow compares properties D. React throws warning

βœ… Correct Answer: B

πŸ’‘ Explanation:

React only checks reference, not deep equality. New object β†’ re-render.

❌ Others:

  • A: Wrong β€” reference changed
  • C: React does NOT deep/shallow compare
  • D: No warning

3. What is the biggest risk of putting side effects inside a reducer?

Options:

A. Performance degradation B. Duplicate or inconsistent side effects C. Memory leaks D. Reducer stops working

βœ… Correct Answer: B

πŸ’‘ Explanation:

React may re-run reducers (especially in concurrent mode), causing duplicate API calls or inconsistent behavior.

❌ Others:

  • A: Secondary issue
  • C: Not primary concern
  • D: Reducer still works

4. What guarantees that dispatch does not change between renders?

Options:

A. React memoizes it with useCallback B. It is bound once during hook initialization C. It is recreated every render but optimized D. JavaScript closures

βœ… Correct Answer: B

πŸ’‘ Explanation:

React internally ensures dispatch is stable, created once per hook.

❌ Others:

  • A: Not user-level memoization
  • C: Not recreated
  • D: Partial but not the full reason

5. What happens with multiple synchronous dispatches?

Options:

A. Only last dispatch applies B. Both dispatches apply sequentially C. Only first applies D. Behavior depends on batching

βœ… Correct Answer: B

πŸ’‘ Explanation:

React queues updates β†’ reducer runs twice β†’ both applied.

❌ Others:

  • A/C: Incorrect
  • D: Batching doesn’t skip updates

6. What is the purpose of the third argument in useReducer?

Options:

A. Middleware B. Lazy initialization C. Debugging D. Async dispatch handling

βœ… Correct Answer: B

πŸ’‘ Explanation:

initFn computes initial state once.

❌ Others:

  • A: Not supported
  • C/D: Not related

7. What happens if reducer throws an error?

Options:

A. Ignored silently B. Component crashes C. State resets D. React retries reducer

βœ… Correct Answer: B

πŸ’‘ Explanation:

Reducers run during render β†’ error propagates β†’ nearest error boundary.

❌ Others:

  • A: No silent fail
  • C: No reset
  • D: No retry

8. Which scenario justifies using useReducer over useState?

Options:

A. Managing a single boolean B. Handling multiple independent states C. Complex state transitions dependent on previous state D. Static values

βœ… Correct Answer: C

πŸ’‘ Explanation:

Reducer shines when transitions are complex and interdependent.

❌ Others:

  • A/B/D: Better suited for useState

9. What is a key downside of combining useReducer with useContext?

Options:

A. Dispatch becomes unstable B. All consumers re-render on state change C. Reducer cannot handle nested state D. Actions become async

βœ… Correct Answer: B

πŸ’‘ Explanation:

Context triggers re-render for all consumers.

❌ Others:

  • A: Dispatch is stable
  • C: Reducer can handle nested state
  • D: Actions remain sync

10. What is the effect of missing a default case in reducer?

Options:

A. React throws error B. State becomes undefined C. No effect D. Reducer stops executing

βœ… Correct Answer: B

πŸ’‘ Explanation:

If no case matches and no default β†’ returns undefined β†’ breaks state.

❌ Others:

  • A/D: Not automatic
  • C: Incorrect

11. Why are action objects preferred over direct function calls?

Options:

A. Faster execution B. Easier serialization and debugging C. Required by React D. Enables async behavior

βœ… Correct Answer: B

πŸ’‘ Explanation:

Action objects:
  • Loggable
  • Serializable
  • Traceable

❌ Others:

  • A: No speed benefit
  • C: Not required
  • D: Not inherent

12. What is the biggest issue with deeply nested state updates?

Options:

A. Performance B. Verbosity and maintainability C. React incompatibility D. Dispatch failure

βœ… Correct Answer: B

πŸ’‘ Explanation:

Deep updates become:
  • Hard to read
  • Error-prone

❌ Others:

  • A: Minor
  • C/D: Not true

13. Why is this pattern problematic?

Options:

A. Random values not allowed B. Breaks purity expectations C. Causes memory leaks D. No issue

βœ… Correct Answer: B

πŸ’‘ Explanation:

Reducers should be deterministic; randomness breaks predictability.

❌ Others:

  • A: Not restricted
  • C: No leak
  • D: Incorrect

14. What happens if reducer returns undefined?

Options:

A. React ignores update B. Component crashes C. State becomes undefined D. React retries reducer

βœ… Correct Answer: C

πŸ’‘ Explanation:

State becomes undefined, likely causing runtime issues.

❌ Others:

  • A: Not ignored
  • B: Not immediate crash
  • D: No retry

15. How does useReducer help in modeling state machines?

Options:

A. By storing multiple states B. By enforcing valid transitions C. By preventing re-renders D. By batching updates

βœ… Correct Answer: B

πŸ’‘ Explanation:

Reducer defines allowed transitions β†’ avoids invalid states.

❌ Others:

  • A: Not unique
  • C/D: Unrelated

16. What is the consequence of dispatching inside render?

Options:

A. One extra render B. Infinite re-render loop C. No effect D. React warning only

βœ… Correct Answer: B

πŸ’‘ Explanation:

Dispatch β†’ state update β†’ render β†’ dispatch again β†’ infinite loop.

❌ Others:

  • A: Not limited
  • C: Incorrect
  • D: It crashes, not just warns

17. Why is splitting reducers beneficial?

Options:

A. Improves React performance automatically B. Improves maintainability and separation C. Reduces memory usage D. Enables async reducers

βœ… Correct Answer: B

πŸ’‘ Explanation:

Separation of concerns β†’ easier scaling and debugging.

❌ Others:

  • A: Not automatic
  • C: Minimal impact
  • D: Not related

18. What is a subtle performance issue with large reducers?

Options:

A. React skips updates B. Reducer runs on every dispatch C. Dispatch becomes async D. State becomes stale

βœ… Correct Answer: B

πŸ’‘ Explanation:

Every dispatch executes reducer β†’ large logic can slow updates.

❌ Others:

  • A: Not true
  • C: Dispatch is sync
  • D: Not inherent

πŸ”š Final Insight

At a senior level, these questions test whether you understand:
  • State identity vs value
  • Purity and concurrency implications
  • Architectural trade-offs
  • Real-world scaling issues

🧠 Advanced useReducer Coding Problems (Senior-Level)


1. Shopping Cart with Derived Totals

🧩 Problem

Build a shopping cart where:
  • Users can add/remove/update items
  • Each item has price, quantity
  • Show total items and total price

βš™οΈ Constraints

  • Avoid recalculating totals outside reducer
  • Handle duplicate items (merge quantities)

βœ… Expected Behavior

⚠️ Edge Cases

  • Removing non-existent item
  • Quantity = 0 β†’ remove item

🧠 Solution Approach

Step 1: State Shape

Step 2: Reducer Logic

Step 3: Why reducer?

  • Derived state consistency
  • Avoid scattered logic

2. Multi-Step Form Wizard

🧩 Problem

Create a form with multiple steps:
  • Step navigation (next/back)
  • Store form data across steps
  • Reset functionality

βš™οΈ Constraints

  • Cannot lose previous step data
  • Validation per step

βœ… Expected Behavior

  • Step 1 β†’ Step 2 β†’ Back β†’ data persists

⚠️ Edge Cases

  • Jumping steps
  • Invalid inputs

🧠 Solution

State

Reducer

Insight

Reducer ensures state + navigation consistency

3. Undo/Redo System

🧩 Problem

Implement undo/redo functionality for text editing.

βš™οΈ Constraints

  • Maintain history
  • Limit history size (e.g., 10)

βœ… Expected

⚠️ Edge Cases

  • Undo beyond history
  • Redo after new action β†’ clear redo stack

🧠 Solution

State

Reducer

WHY

Reducer models state timeline

4. API Request State Manager

🧩 Problem

Handle API states:
  • loading
  • success
  • error

βš™οΈ Constraints

  • Avoid inconsistent states

βœ… Expected

⚠️ Edge Cases

  • Multiple requests
  • Stale responses

🧠 Solution


5. Dynamic Form Builder

🧩 Problem

Form fields are dynamic (add/remove fields at runtime)

βš™οΈ Constraints

  • Fields stored as array
  • Each field has validation

⚠️ Edge Cases

  • Duplicate field IDs
  • Removing active field

🧠 Solution

Reducer manages:

6. Notification Queue System

🧩 Problem

Manage toast notifications:
  • Add/remove notifications
  • Auto-dismiss

βš™οΈ Constraints

  • FIFO order

⚠️ Edge Cases

  • Duplicate messages
  • Rapid dispatch

🧠 Solution


7. File Upload Manager

🧩 Problem

Track multiple file uploads with progress

βš™οΈ Constraints

  • Each file has progress %
  • Handle cancel

⚠️ Edge Cases

  • Cancel mid-upload
  • Retry

🧠 Solution


8. Role-Based Access Control

🧩 Problem

Manage user roles and permissions dynamically

βš™οΈ Constraints

  • Roles can change at runtime

⚠️ Edge Cases

  • Conflicting permissions

🧠 Solution

Reducer enforces:

9. Drag-and-Drop List Reordering

🧩 Problem

Reorder items in a list

βš™οΈ Constraints

  • Maintain immutability

⚠️ Edge Cases

  • Same index move
  • Invalid indices

🧠 Solution


10. Theme Manager (Global State)

🧩 Problem

Toggle and persist theme

βš™οΈ Constraints

  • Sync with localStorage

⚠️ Edge Cases

  • Initial load mismatch

🧠 Solution

Reducer + useEffect

11. Pagination State Manager

🧩 Problem

Handle page navigation + page size

βš™οΈ Constraints

  • Reset page on size change

⚠️ Edge Cases

  • Out-of-range pages

🧠 Solution


12. Form Validation Engine

🧩 Problem

Validate multiple fields with rules

βš™οΈ Constraints

  • Real-time validation

⚠️ Edge Cases

  • Async validation

🧠 Solution

Reducer stores:

13. Shopping Wishlist with Sync

🧩 Problem

Sync wishlist with backend

βš™οΈ Constraints

  • Optimistic updates

⚠️ Edge Cases

  • API failure rollback

🧠 Solution


14. Tab Manager

🧩 Problem

Manage dynamic tabs

βš™οΈ Constraints

  • Only one active tab

⚠️ Edge Cases

  • Closing active tab

🧠 Solution


15. Keyboard Shortcut Manager

🧩 Problem

Map keyboard shortcuts to actions

βš™οΈ Constraints

  • Prevent conflicts

⚠️ Edge Cases

  • Duplicate bindings

🧠 Solution

Reducer manages:

16. Collaborative Cursor Tracker

🧩 Problem

Track multiple user cursors (like Figma)

βš™οΈ Constraints

  • Real-time updates

⚠️ Edge Cases

  • Disconnect cleanup

🧠 Solution


17. Filter + Sort Engine

🧩 Problem

Apply filters and sorting to dataset

βš™οΈ Constraints

  • Combine multiple filters

⚠️ Edge Cases

  • Empty results

🧠 Solution

Reducer manages:

18. Chat Message Buffer

🧩 Problem

Handle incoming messages + scroll behavior

βš™οΈ Constraints

  • Limit buffer size

⚠️ Edge Cases

  • Duplicate messages

🧠 Solution


19. Game State Manager (Finite State Machine)

🧩 Problem

Game states:
  • idle β†’ playing β†’ paused β†’ game over

βš™οΈ Constraints

  • Invalid transitions not allowed

⚠️ Edge Cases

  • Pause from idle

🧠 Solution

Reducer enforces transitions

πŸ”š Final Thought

These problems test:
  • State modeling
  • Reducer design
  • Edge-case thinking
  • Real-world architecture

🧠 Advanced useReducer Debugging Challenges (Senior-Level)


1. Silent State Mutation Bug

🐞 Buggy Code

❌ What’s Wrong

State is being mutated directly.

πŸ€” WHY it happens

React relies on reference equality (Object.is). Returning the same object prevents re-render.

βœ… Fix

🧠 Best Practice

Always treat state as immutable.

2. Missing Default Case Crash

🐞 Buggy Code

❌ What’s Wrong

No return for unknown actions β†’ returns undefined.

πŸ€” WHY

React expects reducer to always return valid state.

βœ… Fix

🧠 Best Practice

Always include a default fallback.

3. Infinite Re-render Loop

🐞 Buggy Code

❌ What’s Wrong

Dispatch inside render.

πŸ€” WHY

Dispatch β†’ state update β†’ render β†’ dispatch again β†’ infinite loop.

βœ… Fix

🧠 Best Practice

Never trigger state updates during render.

4. Async Logic Inside Reducer

🐞 Buggy Code

❌ What’s Wrong

Side effects inside reducer.

πŸ€” WHY

Reducers must be pure; React may re-run them.

βœ… Fix

🧠 Best Practice

Keep reducers pure and synchronous.

5. Stale State Assumption

🐞 Buggy Code

❌ What’s Wrong

Expecting updated state immediately.

πŸ€” WHY

State updates are scheduled, not immediate.

βœ… Fix

Use useEffect:

🧠 Best Practice

Treat state updates as async from UI perspective.

6. Recreating Initial State Expensively

🐞 Buggy Code

❌ What’s Wrong

expensiveInit() runs on every render.

πŸ€” WHY

Initializer is executed immediately.

βœ… Fix

🧠 Best Practice

Use lazy initialization.

7. Deeply Nested State Update Bug

🐞 Buggy Code

❌ What’s Wrong

Overwrites entire user.profile structure.

πŸ€” WHY

Missing spread for nested objects.

βœ… Fix

🧠 Best Practice

Always preserve nested structure.

8. Dispatching Wrong Action Shape

🐞 Buggy Code

❌ What’s Wrong

Reducer expects object, not string.

πŸ€” WHY

Mismatch in action contract.

βœ… Fix

🧠 Best Practice

Standardize action shape.

9. Unnecessary Re-renders with Context

🐞 Buggy Code

❌ What’s Wrong

New object every render β†’ re-renders all consumers.

πŸ€” WHY

Reference changes trigger context updates.

βœ… Fix

🧠 Best Practice

Memoize provider values.

10. Reducer Too Large (Performance Issue)

🐞 Buggy Code

❌ What’s Wrong

Heavy computation on every dispatch.

πŸ€” WHY

Reducer runs for every action.

βœ… Fix

Split reducers:

🧠 Best Practice

Keep reducers small and focused.

11. Returning New Object Unnecessarily

🐞 Buggy Code

❌ What’s Wrong

Triggers unnecessary re-render.

πŸ€” WHY

New reference even if no change.

βœ… Fix

🧠 Best Practice

Return same reference if unchanged.

12. Using Random Values in Reducer

🐞 Buggy Code

❌ What’s Wrong

Non-deterministic reducer.

πŸ€” WHY

Breaks predictability.

βœ… Fix

Generate outside reducer.

🧠 Best Practice

Reducers must be deterministic.

13. Forgetting to Handle Edge Action

🐞 Buggy Code

❌ What’s Wrong

Fails if action.id undefined.

πŸ€” WHY

No validation.

βœ… Fix

🧠 Best Practice

Validate action payloads.

14. Using Reducer for Simple State

🐞 Buggy Code

❌ What’s Wrong

Over-engineered.

πŸ€” WHY

No complex logic.

βœ… Fix

Use useState.

🧠 Best Practice

Choose the right abstraction.

15. State Reset Bug

🐞 Buggy Code

❌ What’s Wrong

initialState might be stale or mutated.

πŸ€” WHY

Shared reference issues.

βœ… Fix

🧠 Best Practice

Avoid shared mutable references.

16. Dispatch Inside Loop

🐞 Buggy Code

❌ What’s Wrong

Multiple re-renders.

πŸ€” WHY

Each dispatch triggers update.

βœ… Fix

Batch updates or single action.

🧠 Best Practice

Minimize dispatch frequency.

17. Ignoring Action Payload Shape

🐞 Buggy Code

❌ What’s Wrong

Assumes payload shape blindly.

πŸ€” WHY

Runtime crashes if payload invalid.

βœ… Fix

Validate payload.

🧠 Best Practice

Use type-safe patterns.

πŸ”š Final Thought

These bugs reflect real production issues:
  • Identity vs mutation
  • Concurrency assumptions
  • Performance pitfalls
  • Architectural misuse

🧠 Real-World Machine Coding Problems using useReducer (Senior-Level)


1. Advanced E-commerce Cart System

🧩 Requirements

  • Add/remove/update items
  • Support discounts, coupons, taxes
  • Multi-currency support
  • Persist cart (localStorage)

πŸ–₯️ UI Behavior

  • Live updates on quantity change
  • Coupon apply/remove UI
  • Price breakdown (subtotal, tax, total)

πŸ”„ State Flow

  • Actions: ADD_ITEM, REMOVE_ITEM, APPLY_COUPON, SET_CURRENCY
  • Derived values computed inside reducer

⚠️ Edge Cases

  • Invalid coupon
  • Currency switch recalculation
  • Negative totals

⚑ Performance

  • Avoid recalculating totals on every render
  • Memoize currency conversions

πŸ—οΈ Architecture

  • Single reducer with normalized state
  • Optional split: pricingReducer, cartReducer

🧠 Approach

  1. Define normalized state (itemsById)
  2. Handle item merge logic
  3. Compute totals inside reducer
  4. Sync with storage via useEffect

2. Collaborative Kanban Board (Trello-like)

🧩 Requirements

  • Drag/drop cards across columns
  • Real-time updates (simulate via actions)
  • Add/edit/delete cards

πŸ–₯️ UI Behavior

  • Smooth drag animations
  • Column-wise grouping

πŸ”„ State Flow

⚠️ Edge Cases

  • Dropping in same position
  • Missing card references

⚑ Performance

  • Avoid re-rendering entire board
  • Use memoized selectors

πŸ—οΈ Architecture

  • Split reducers: boardReducer, cardReducer

🧠 Approach

  1. Normalize data
  2. Handle MOVE_CARD action carefully
  3. Ensure immutability for lists

3. Real-Time Chat Application

🧩 Requirements

  • Send/receive messages
  • Typing indicators
  • Message status (sent/read)

πŸ–₯️ UI Behavior

  • Scroll to latest message
  • Show typing users

πŸ”„ State Flow

⚠️ Edge Cases

  • Duplicate messages
  • Out-of-order delivery

⚑ Performance

  • Limit message buffer
  • Virtualize message list

πŸ—οΈ Architecture

  • messageReducer + uiReducer

🧠 Approach

  1. Deduplicate messages
  2. Maintain message IDs
  3. Handle status updates

4. Form Builder (Dynamic + Conditional Logic)

🧩 Requirements

  • Add/remove fields dynamically
  • Conditional visibility (if X β†’ show Y)
  • Validation rules

πŸ–₯️ UI Behavior

  • Fields appear/disappear dynamically

πŸ”„ State Flow

  • fields config + values + errors

⚠️ Edge Cases

  • Circular dependencies
  • Hidden field validation

⚑ Performance

  • Avoid recalculating all conditions

πŸ—οΈ Architecture

  • Separate config vs runtime state

🧠 Approach

  1. Store field schema
  2. Evaluate conditions in reducer
  3. Trigger validations on change

5. Infinite Scroll Feed (Social Media)

🧩 Requirements

  • Fetch paginated data
  • Merge results
  • Handle loading/error

πŸ–₯️ UI Behavior

  • Scroll triggers fetch
  • Loader at bottom

πŸ”„ State Flow

⚠️ Edge Cases

  • Duplicate pages
  • Rapid scroll triggering

⚑ Performance

  • Debounce fetch
  • Prevent duplicate requests

πŸ—οΈ Architecture

  • fetchReducer (FSM-like)

🧠 Approach

  1. Track page state
  2. Append new data
  3. Prevent parallel fetches

6. Multi-Tab Session Manager

🧩 Requirements

  • Manage multiple tabs (like browser tabs)
  • Persist tab state
  • Restore sessions

πŸ–₯️ UI Behavior

  • Switch tabs instantly
  • Close/open tabs

πŸ”„ State Flow

⚠️ Edge Cases

  • Closing active tab
  • Duplicate tab IDs

⚑ Performance

  • Avoid re-rendering inactive tabs

πŸ—οΈ Architecture

  • tabReducer + contentReducer

🧠 Approach

  1. Maintain tab registry
  2. Handle active switching
  3. Persist in storage

7. Advanced Filter Engine (E-commerce/Search)

🧩 Requirements

  • Multi-select filters
  • Range filters
  • Sort options

πŸ–₯️ UI Behavior

  • Real-time filtering

πŸ”„ State Flow

⚠️ Edge Cases

  • Conflicting filters
  • Empty results

⚑ Performance

  • Memoize filtering logic

πŸ—οΈ Architecture

  • filterReducer + dataReducer

🧠 Approach

  1. Store raw data separately
  2. Apply filters in reducer or selector
  3. Optimize with memoization

8. Notification Center with Priorities

🧩 Requirements

  • Queue notifications
  • Priority-based ordering
  • Auto-dismiss

⚠️ Edge Cases

  • Duplicate notifications
  • Expired notifications

⚑ Performance

  • Limit queue size

🧠 Approach

  • Priority queue logic in reducer

9. File Upload Dashboard

🧩 Requirements

  • Upload multiple files
  • Track progress
  • Retry/cancel

πŸ”„ State Flow

⚠️ Edge Cases

  • Network failure
  • Partial uploads

⚑ Performance

  • Avoid updating entire list

🧠 Approach

  • Update specific file entry

10. Undo/Redo Rich Text Editor

🧩 Requirements

  • Full history tracking
  • Keyboard shortcuts

⚠️ Edge Cases

  • Large history memory

⚑ Performance

  • Limit history size

🧠 Approach

  • past/present/future structure

11. Permissions Management Dashboard

🧩 Requirements

  • Assign roles
  • Toggle permissions

⚠️ Edge Cases

  • Conflicting rules

🧠 Approach

  • Normalize roles + permissions

12. Scheduling Calendar (Google Calendar-like)

🧩 Requirements

  • Add/edit events
  • Handle overlaps

⚠️ Edge Cases

  • Time conflicts

⚑ Performance

  • Efficient time lookup

🧠 Approach

  • Store events indexed by date

13. Shopping Checkout Flow (Multi-step + Validation)

🧩 Requirements

  • Steps: Address β†’ Payment β†’ Review
  • Validation per step

⚠️ Edge Cases

  • Partial completion

🧠 Approach

  • FSM-like reducer

14. Data Grid with Inline Editing

🧩 Requirements

  • Edit rows inline
  • Bulk updates

⚠️ Edge Cases

  • Validation errors

⚑ Performance

  • Row-level updates

🧠 Approach

  • Normalize rows by ID

15. Real-Time Stock Dashboard

🧩 Requirements

  • Live price updates
  • Highlight changes

⚠️ Edge Cases

  • Rapid updates

⚑ Performance

  • Throttle updates

🧠 Approach

  • Update only changed stocks

16. Feature Flag System

🧩 Requirements

  • Enable/disable features dynamically

⚠️ Edge Cases

  • Dependency between flags

🧠 Approach

  • Reducer enforces rules

πŸ”š Final Insight

These problems test architectural thinking, not just coding:
  • State normalization
  • Reducer composition
  • Performance optimization
  • Edge-case handling
  • Real-world constraints

🧠 Senior-Level Interview Questions β€” useReducer


1. When would you choose useReducer over useState in a real production system?

πŸ” Follow-up

  • What signals tell you state is β€œcomplex enough”?
  • Can you refactor from useState to useReducer safely?

βœ… Strong Answer

Use useReducer when:
  • State transitions are interdependent
  • Multiple state variables must change atomically
  • Logic is reused or needs testability
Example:

❌ Weak Answer

β€œWhen state is complex.”
πŸ‘‰ Fails because it doesn’t define what complexity means or give criteria.

2. How does React decide whether to re-render after a reducer update?

πŸ” Follow-up

  • What happens if you mutate state?
  • Does React do deep comparison?

βœ… Strong Answer

React uses reference equality (Object.is). If reducer returns the same reference β†’ no re-render.

❌ Weak Answer

β€œReact checks if values changed.”
πŸ‘‰ Incorrect β€” React does NOT deep compare.

3. Explain why reducers must be pure, especially in React 18+.

πŸ” Follow-up

  • What breaks in concurrent rendering?
  • Give a real bug example

βœ… Strong Answer

Reducers may be re-run or replayed in concurrent rendering. Impure reducers cause:
  • Duplicate API calls
  • Inconsistent state

❌ Weak Answer

β€œBecause Redux says so.”
πŸ‘‰ No understanding of React’s execution model.

4. Design a global state system using useReducer and useContext. What are the trade-offs?

πŸ” Follow-up

  • How do you prevent unnecessary re-renders?
  • When would you switch to Redux/Zustand?

βœ… Strong Answer

  • Use reducer for logic, context for distribution
  • Split contexts or memoize value
Trade-offs:
  • Simpler than Redux
  • But causes full tree re-renders

❌ Weak Answer

β€œIt replaces Redux.”
πŸ‘‰ Oversimplification β€” ignores scaling issues.

5. How would you debug a reducer that behaves inconsistently in production but not locally?

πŸ” Follow-up

  • What tools/strategies?
  • What assumptions would you question?

βœ… Strong Answer

  • Log actions + state transitions
  • Check for impure logic
  • Validate concurrency assumptions

❌ Weak Answer

β€œAdd console logs.”
πŸ‘‰ Too shallow β€” no strategy.

6. What are the performance implications of large reducers?

πŸ” Follow-up

  • How would you optimize?
  • When to split reducers?

βœ… Strong Answer

Reducers run on every dispatch β†’ large logic slows updates. Optimize via:
  • Splitting reducers
  • Memoized selectors

❌ Weak Answer

β€œReducers are fast.”
πŸ‘‰ Ignores scale.

7. How would you model a finite state machine using useReducer?

πŸ” Follow-up

  • How do you prevent invalid transitions?

βœ… Strong Answer

Use state + allowed transitions:
Ensures controlled transitions

❌ Weak Answer

β€œUse switch case.”
πŸ‘‰ Misses FSM concept.

8. What is a subtle bug caused by returning a new object unnecessarily?

πŸ” Follow-up

  • How does this impact performance?

βœ… Strong Answer

Triggers unnecessary re-renders:

❌ Weak Answer

β€œNo issue.”
πŸ‘‰ Misses rendering implications.

9. How would you handle async flows with useReducer?

πŸ” Follow-up

  • Why not inside reducer?
  • Compare with Redux middleware

βœ… Strong Answer

Use useEffect to dispatch lifecycle actions:
Reducer remains pure.

❌ Weak Answer

β€œPut fetch in reducer.”
πŸ‘‰ Violates purity.

10. How do you avoid unnecessary re-renders when using useReducer with Context?

πŸ” Follow-up

  • What patterns help?

βœ… Strong Answer

  • Split contexts
  • Memoize provider value
  • Use selector-based consumption

❌ Weak Answer

β€œUse memo.”
πŸ‘‰ Too vague.

11. What are the trade-offs of normalizing state in reducers?

πŸ” Follow-up

  • When is normalization overkill?

βœ… Strong Answer

Pros:
  • Easier updates
  • Avoid deep nesting
Cons:
  • More complex structure

❌ Weak Answer

β€œAlways normalize.”
πŸ‘‰ Not always necessary.

12. Explain a real-world scenario where useReducer improves debugging.

πŸ” Follow-up

  • How would you log actions?

βœ… Strong Answer

Action-based updates β†’ easier tracing:

❌ Weak Answer

β€œIt’s easier.”
πŸ‘‰ No concrete reasoning.

13. How does batching affect multiple dispatch calls?

πŸ” Follow-up

  • Does React skip any updates?

βœ… Strong Answer

React batches but processes all actions sequentially.

❌ Weak Answer

β€œOnly last dispatch runs.”
πŸ‘‰ Incorrect.

14. What’s the risk of deeply nested state in reducers?

πŸ” Follow-up

  • How would you refactor?

βœ… Strong Answer

  • Verbose updates
  • Error-prone
Solution:
  • Normalize state
  • Split reducers

❌ Weak Answer

β€œIt’s fine.”
πŸ‘‰ Ignores maintainability.

15. How would you design undo/redo using useReducer?

πŸ” Follow-up

  • What data structure?

βœ… Strong Answer

Use:

❌ Weak Answer

β€œStore previous state.”
πŸ‘‰ Too vague.

16. When does useReducer become an anti-pattern?

πŸ” Follow-up

  • Give real examples

βœ… Strong Answer

  • Simple toggles
  • Independent state

❌ Weak Answer

β€œNever.”
πŸ‘‰ Shows poor judgment.

17. How does dispatch stability influence component design?

πŸ” Follow-up

  • Do you need useCallback?

βœ… Strong Answer

Dispatch is stable β†’ safe to pass down.

❌ Weak Answer

β€œWrap in useCallback.”
πŸ‘‰ Unnecessary optimization.

πŸ” Follow-up

  • How to fix?

βœ… Strong Answer

Using outdated state outside reducer logic. Fix with:
  • Proper dependencies
  • Moving logic into reducer

❌ Weak Answer

β€œNot sure.”
πŸ‘‰ Misses real-world issue.

19. How would you scale useReducer in a large application?

πŸ” Follow-up

  • When to move to external state library?

βœ… Strong Answer

  • Split reducers
  • Use context layering
  • Move to Redux/Zustand when:
    • Cross-cutting state grows

❌ Weak Answer

β€œJust use one reducer.”
πŸ‘‰ Not scalable.

20. What mental model do you use when designing reducers?

πŸ” Follow-up

  • How do you ensure correctness?

βœ… Strong Answer

Think of reducer as:
State machine with explicit transitions
Ensures predictability and testability.

❌ Weak Answer

β€œJust switch case logic.”
πŸ‘‰ Lacks abstraction.

πŸ”š Final Insight

A strong candidate demonstrates:
  • State modeling skills
  • Understanding of React internals
  • Trade-off awareness
  • Debugging mindset
Not just β€œhow to use useReducer”, but:
When, why, and how it behaves under real-world constraints.