> ## Documentation Index
> Fetch the complete documentation index at: https://docs.anujpandey.in/llms.txt
> Use this file to discover all available pages before exploring further.

# useReducer

# 📘 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.

```js theme={null}
(state, action) => newState
```

* Receives current state
* Receives an action
* Returns new state (immutable update)

***

### 2. Action

An object describing **what happened**

```js theme={null}
{ type: "INCREMENT" }
{ type: "ADD_TODO", payload: "Learn React" }
```

***

### 3. Dispatch

A function used to **trigger state changes**

```js theme={null}
dispatch({ type: "INCREMENT" });
```

***

### 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

```js theme={null}
const [state, dispatch] = useReducer(reducer, initialState);
```

***

## 🔹 Example 1: Counter

```js theme={null}
import React, { useReducer } from "react";

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

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

  return (
    <div>
      <p>{state.count}</p>
      <button onClick={() => dispatch({ type: "increment" })}>
        +
      </button>
      <button onClick={() => dispatch({ type: "decrement" })}>
        -
      </button>
    </div>
  );
}
```

***

## 🔹 Example 2: Complex State Object

```js theme={null}
const reducer = (state, action) => {
  switch (action.type) {
    case "updateName":
      return { ...state, name: action.payload };
    case "updateAge":
      return { ...state, age: action.payload };
    default:
      return state;
  }
};
```

***

## 🔹 Example 3: Todo List

```js theme={null}
const reducer = (state, action) => {
  switch (action.type) {
    case "add":
      return [...state, { id: Date.now(), text: action.payload }];
    case "remove":
      return state.filter(todo => todo.id !== action.payload);
    default:
      return state;
  }
};
```

***

## 🔹 Example 4: Lazy Initialization

```js theme={null}
const init = (initialValue) => {
  return { count: initialValue };
};

const [state, dispatch] = useReducer(reducer, 10, init);
```

👉 Useful when initial state is expensive to compute

***

## 🔹 Example 5: useReducer + useContext

```js theme={null}
const AppContext = React.createContext();

const AppProvider = ({ children }) => {
  const [state, dispatch] = useReducer(reducer, initialState);

  return (
    <AppContext.Provider value={{ state, dispatch }}>
      {children}
    </AppContext.Provider>
  );
};
```

***

## 🔹 Mini Variations

### Dispatch with payload

```js theme={null}
dispatch({ type: "SET_VALUE", payload: 42 });
```

***

### Multiple reducers (manual composition)

```js theme={null}
const rootReducer = (state, action) => ({
  user: userReducer(state.user, action),
  cart: cartReducer(state.cart, action),
});
```

***

# 4. Edge Cases / Common Mistakes

***

## 🔴 1. Mutating state directly

❌ Wrong:

```js theme={null}
state.count += 1;
return state;
```

✅ Correct:

```js theme={null}
return { ...state, count: state.count + 1 };
```

👉 Mutation prevents React from detecting changes

***

## 🔴 2. Returning same reference

```js theme={null}
return state;
```

👉 No re-render occurs

***

## 🔴 3. Missing default case

```js theme={null}
default:
  return state;
```

👉 Without this, unexpected bugs may occur

***

## 🔴 4. Dispatch inside render

```js theme={null}
dispatch({ type: "increment" }); // ❌ BAD
```

👉 Causes infinite re-renders

***

## 🔴 5. Overusing useReducer

👉 Not every state needs reducer logic
👉 Adds unnecessary complexity

***

## 🔴 6. Deep nested updates

```js theme={null}
return {
  ...state,
  user: {
    ...state.user,
    profile: {
      ...state.user.profile,
      name: action.payload
    }
  }
};
```

👉 Hard to maintain → consider normalization

***

## 🔴 7. Async logic inside reducer

❌ Avoid:

```js theme={null}
case "fetch":
  fetch(...);
```

👉 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

```js theme={null}
const ACTIONS = {
  INCREMENT: "increment",
  DECREMENT: "decrement"
};
```

👉 Prevents typos and improves maintainability

***

## ✅ 3. Group related logic

* 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:

```js theme={null}
{
  users: {
    byId: {},
    allIds: []
  }
}
```

***

## ✅ 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

```js theme={null}
useReducer(reducer, initialArg, init);
```

***

## ✅ 9. Debugging strategy

* Log actions inside reducer:

```js theme={null}
console.log(action);
```

* Track state transitions

***

## ✅ 10. Testing reducers

* Reducers are pure → easy to test

```js theme={null}
expect(reducer({ count: 0 }, { type: "increment" }))
  .toEqual({ count: 1 });
```

***

# 🧠 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

| Aspect            | `useState`    | `useReducer`       |
| ----------------- | ------------- | ------------------ |
| API               | Simple setter | Dispatch + reducer |
| Logic location    | Inline        | Centralized        |
| State transitions | Implicit      | Explicit           |

### ⚙️ Internal Insight

React internally does something like:

```js theme={null}
// Conceptually
function useState(initial) {
  return useReducer((state, action) => action, initial);
}
```

### 🧠 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

```js theme={null}
function reducer(state, action) {
  fetch("/api"); // ❌ side effect
  return state;
}
```

### 🔥 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`)**.

```js theme={null}
if (Object.is(prevState, newState)) {
  // No re-render
}
```

### 🔴 Subtle Bug

```js theme={null}
state.count++;
return state; // ❌ same reference
```

👉 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

| Feature     | `useReducer` | Redux  |
| ----------- | ------------ | ------ |
| Scope       | Local        | Global |
| Middleware  | ❌            | ✅      |
| DevTools    | ❌            | ✅      |
| Boilerplate | Low          | High   |

### 🧠 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**.

```js theme={null}
const [state, dispatch] = useReducer(...);
// dispatch !== recreated on re-render
```

### 🧠 WHY

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

### 🔥 Contrast

```js theme={null}
const fn = () => {}; // recreated every render
```

***

## 6. What happens if multiple dispatches occur synchronously?

### ✅ Answer

React **batches updates**.

```js theme={null}
dispatch({ type: "increment" });
dispatch({ type: "increment" });
```

### 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

```js theme={null}
const [state, dispatch] = useReducer(reducer, initialArg, init);
```

### 🧠 WHY

* `init` runs **only once**
* Avoids recomputation on every render

### 🔥 Use case

```js theme={null}
const init = () => expensiveCalculation();
```

***

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

### ✅ Answer

### 🔹 Pattern: Reducer Composition

```js theme={null}
const rootReducer = (state, action) => ({
  user: userReducer(state.user, action),
  cart: cartReducer(state.cart, action),
});
```

### 🧠 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

```js theme={null}
case "FETCH":
  fetch("/api"); // ❌
```

### ✅ Correct

```js theme={null}
useEffect(() => {
  fetchData().then(data =>
    dispatch({ type: "SUCCESS", payload: data })
  );
}, []);
```

### 🧠 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

```js theme={null}
return {
  ...state,
  user: {
    ...state.user,
    profile: {
      ...state.user.profile,
      name: action.payload
    }
  }
};
```

### 🔴 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

```js theme={null}
const [count, setCount] = useState(0); // better
```

### 🧠 WHY

* Adds unnecessary abstraction
* Reduces readability

***

## 13. How do you debug complex reducer logic?

### ✅ Answer

### 🔹 Techniques

1. Log actions

```js theme={null}
console.log(action);
```

2. Trace state transitions

3. Use custom middleware-like wrappers

```js theme={null}
const dispatchWithLog = action => {
  console.log(action);
  dispatch(action);
};
```

### 🧠 WHY

Reducers are deterministic → easy to trace

***

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

### ✅ Answer

### 🔹 Pattern

```js theme={null}
const Context = createContext();

const Provider = ({ children }) => {
  const [state, dispatch] = useReducer(reducer, initialState);
  return (
    <Context.Provider value={{ state, dispatch }}>
      {children}
    </Context.Provider>
  );
};
```

### 🧠 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

```js theme={null}
dispatch({ type: "ADD_TODO", payload: "Task" });
```

### 🧠 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

```js theme={null}
const reducer = (state, action) => {
  switch (state.status) {
    case "idle":
      if (action.type === "FETCH") return { status: "loading" };
      break;
    case "loading":
      if (action.type === "SUCCESS") return { status: "success" };
      break;
  }
  return state;
};
```

### 🧠 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:**

```js theme={null}
function reducer(state, action) {
  switch (action.type) {
    case "increment":
      state.count += 1;
      return state;
    default:
      return state;
  }
}
```

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?

```js theme={null}
dispatch({ type: "inc" });
dispatch({ type: "inc" });
```

### 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:

```js theme={null}
useReducer(reducer, initialArg, initFn);
```

`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?

```js theme={null}
dispatch({ type: "SET", payload: Math.random() });
```

### 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?

```js theme={null}
dispatch({ type: "increment" });
```

### 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

```js theme={null}
addItem({ id: 1, price: 100 })
addItem({ id: 1, price: 100 })
→ quantity = 2, total = 200
```

## ⚠️ Edge Cases

* Removing non-existent item
* Quantity = 0 → remove item

## 🧠 Solution Approach

### Step 1: State Shape

```js theme={null}
{
  items: [],
  totalPrice: 0,
  totalItems: 0
}
```

### Step 2: Reducer Logic

```js theme={null}
function reducer(state, action) {
  switch (action.type) {
    case "ADD":
      // merge or insert
    case "REMOVE":
    case "UPDATE_QTY":
  }
}
```

### 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

```js theme={null}
{
  step: 1,
  data: {
    name: "",
    email: ""
  }
}
```

### Reducer

```js theme={null}
case "NEXT":
case "BACK":
case "UPDATE_FIELD":
```

### 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

```js theme={null}
type "A" → "AB" → undo → "A"
```

## ⚠️ Edge Cases

* Undo beyond history
* Redo after new action → clear redo stack

## 🧠 Solution

### State

```js theme={null}
{
  past: [],
  present: "",
  future: []
}
```

### Reducer

```js theme={null}
case "TYPE":
case "UNDO":
case "REDO":
```

### WHY

Reducer models **state timeline**

***

# 4. API Request State Manager

## 🧩 Problem

Handle API states:

* loading
* success
* error

## ⚙️ Constraints

* Avoid inconsistent states

## ✅ Expected

```js theme={null}
FETCH → loading
SUCCESS → data
ERROR → error
```

## ⚠️ Edge Cases

* Multiple requests
* Stale responses

## 🧠 Solution

```js theme={null}
{
  status: "idle" | "loading" | "success" | "error",
  data: null,
  error: null
}
```

***

# 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:

```js theme={null}
fields: [{ id, value, error }]
```

***

# 6. Notification Queue System

## 🧩 Problem

Manage toast notifications:

* Add/remove notifications
* Auto-dismiss

## ⚙️ Constraints

* FIFO order

## ⚠️ Edge Cases

* Duplicate messages
* Rapid dispatch

## 🧠 Solution

```js theme={null}
case "ADD_NOTIFICATION"
case "REMOVE_NOTIFICATION"
```

***

# 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

```js theme={null}
files: [{ id, progress, status }]
```

***

# 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:

```js theme={null}
case "SET_ROLE"
case "UPDATE_PERMISSION"
```

***

# 9. Drag-and-Drop List Reordering

## 🧩 Problem

Reorder items in a list

## ⚙️ Constraints

* Maintain immutability

## ⚠️ Edge Cases

* Same index move
* Invalid indices

## 🧠 Solution

```js theme={null}
case "MOVE_ITEM"
```

***

# 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

```js theme={null}
{ page, pageSize }
```

***

# 12. Form Validation Engine

## 🧩 Problem

Validate multiple fields with rules

## ⚙️ Constraints

* Real-time validation

## ⚠️ Edge Cases

* Async validation

## 🧠 Solution

Reducer stores:

```js theme={null}
values, errors
```

***

# 13. Shopping Wishlist with Sync

## 🧩 Problem

Sync wishlist with backend

## ⚙️ Constraints

* Optimistic updates

## ⚠️ Edge Cases

* API failure rollback

## 🧠 Solution

```js theme={null}
case "ADD_OPTIMISTIC"
case "ROLLBACK"
```

***

# 14. Tab Manager

## 🧩 Problem

Manage dynamic tabs

## ⚙️ Constraints

* Only one active tab

## ⚠️ Edge Cases

* Closing active tab

## 🧠 Solution

```js theme={null}
tabs, activeTab
```

***

# 15. Keyboard Shortcut Manager

## 🧩 Problem

Map keyboard shortcuts to actions

## ⚙️ Constraints

* Prevent conflicts

## ⚠️ Edge Cases

* Duplicate bindings

## 🧠 Solution

Reducer manages:

```js theme={null}
shortcuts: {}
```

***

# 16. Collaborative Cursor Tracker

## 🧩 Problem

Track multiple user cursors (like Figma)

## ⚙️ Constraints

* Real-time updates

## ⚠️ Edge Cases

* Disconnect cleanup

## 🧠 Solution

```js theme={null}
cursors: { userId: position }
```

***

# 17. Filter + Sort Engine

## 🧩 Problem

Apply filters and sorting to dataset

## ⚙️ Constraints

* Combine multiple filters

## ⚠️ Edge Cases

* Empty results

## 🧠 Solution

Reducer manages:

```js theme={null}
filters, sort, data
```

***

# 18. Chat Message Buffer

## 🧩 Problem

Handle incoming messages + scroll behavior

## ⚙️ Constraints

* Limit buffer size

## ⚠️ Edge Cases

* Duplicate messages

## 🧠 Solution

```js theme={null}
messages: []
```

***

# 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

```js theme={null}
function reducer(state, action) {
  switch (action.type) {
    case "increment":
      state.count += 1;
      return state;
    default:
      return state;
  }
}
```

## ❌ 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

```js theme={null}
return { ...state, count: state.count + 1 };
```

## 🧠 Best Practice

Always treat state as **immutable**.

***

# 2. Missing Default Case Crash

## 🐞 Buggy Code

```js theme={null}
function reducer(state, action) {
  if (action.type === "increment") {
    return { count: state.count + 1 };
  }
}
```

## ❌ What’s Wrong

No return for unknown actions → returns `undefined`.

## 🤔 WHY

React expects reducer to always return valid state.

## ✅ Fix

```js theme={null}
default:
  return state;
```

## 🧠 Best Practice

Always include a **default fallback**.

***

# 3. Infinite Re-render Loop

## 🐞 Buggy Code

```js theme={null}
function Counter() {
  const [state, dispatch] = useReducer(reducer, { count: 0 });

  dispatch({ type: "increment" });

  return <div>{state.count}</div>;
}
```

## ❌ What’s Wrong

Dispatch inside render.

## 🤔 WHY

Dispatch → state update → render → dispatch again → infinite loop.

## ✅ Fix

```js theme={null}
useEffect(() => {
  dispatch({ type: "increment" });
}, []);
```

## 🧠 Best Practice

Never trigger state updates **during render**.

***

# 4. Async Logic Inside Reducer

## 🐞 Buggy Code

```js theme={null}
function reducer(state, action) {
  switch (action.type) {
    case "fetch":
      fetch("/api").then(() => {});
      return state;
  }
}
```

## ❌ What’s Wrong

Side effects inside reducer.

## 🤔 WHY

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

## ✅ Fix

```js theme={null}
useEffect(() => {
  fetch("/api").then(data =>
    dispatch({ type: "success", payload: data })
  );
}, []);
```

## 🧠 Best Practice

Keep reducers **pure and synchronous**.

***

# 5. Stale State Assumption

## 🐞 Buggy Code

```js theme={null}
dispatch({ type: "increment" });
console.log(state.count);
```

## ❌ What’s Wrong

Expecting updated state immediately.

## 🤔 WHY

State updates are scheduled, not immediate.

## ✅ Fix

Use `useEffect`:

```js theme={null}
useEffect(() => {
  console.log(state.count);
}, [state.count]);
```

## 🧠 Best Practice

Treat state updates as **async from UI perspective**.

***

# 6. Recreating Initial State Expensively

## 🐞 Buggy Code

```js theme={null}
const [state, dispatch] = useReducer(reducer, expensiveInit());
```

## ❌ What’s Wrong

`expensiveInit()` runs on every render.

## 🤔 WHY

Initializer is executed immediately.

## ✅ Fix

```js theme={null}
useReducer(reducer, initialArg, expensiveInit);
```

## 🧠 Best Practice

Use **lazy initialization**.

***

# 7. Deeply Nested State Update Bug

## 🐞 Buggy Code

```js theme={null}
return {
  ...state,
  user: {
    profile: {
      name: action.payload
    }
  }
};
```

## ❌ What’s Wrong

Overwrites entire `user.profile` structure.

## 🤔 WHY

Missing spread for nested objects.

## ✅ Fix

```js theme={null}
return {
  ...state,
  user: {
    ...state.user,
    profile: {
      ...state.user.profile,
      name: action.payload
    }
  }
};
```

## 🧠 Best Practice

Always preserve nested structure.

***

# 8. Dispatching Wrong Action Shape

## 🐞 Buggy Code

```js theme={null}
dispatch("increment");
```

## ❌ What’s Wrong

Reducer expects object, not string.

## 🤔 WHY

Mismatch in action contract.

## ✅ Fix

```js theme={null}
dispatch({ type: "increment" });
```

## 🧠 Best Practice

Standardize action shape.

***

# 9. Unnecessary Re-renders with Context

## 🐞 Buggy Code

```js theme={null}
<Context.Provider value={{ state, dispatch }}>
```

## ❌ What’s Wrong

New object every render → re-renders all consumers.

## 🤔 WHY

Reference changes trigger context updates.

## ✅ Fix

```js theme={null}
const value = useMemo(() => ({ state, dispatch }), [state]);
```

## 🧠 Best Practice

Memoize provider values.

***

# 10. Reducer Too Large (Performance Issue)

## 🐞 Buggy Code

```js theme={null}
function reducer(state, action) {
  // 500+ lines of logic
}
```

## ❌ What’s Wrong

Heavy computation on every dispatch.

## 🤔 WHY

Reducer runs for every action.

## ✅ Fix

Split reducers:

```js theme={null}
combineReducers(...)
```

## 🧠 Best Practice

Keep reducers **small and focused**.

***

# 11. Returning New Object Unnecessarily

## 🐞 Buggy Code

```js theme={null}
return { ...state };
```

## ❌ What’s Wrong

Triggers unnecessary re-render.

## 🤔 WHY

New reference even if no change.

## ✅ Fix

```js theme={null}
return state;
```

## 🧠 Best Practice

Return same reference if unchanged.

***

# 12. Using Random Values in Reducer

## 🐞 Buggy Code

```js theme={null}
case "generate":
  return { value: Math.random() };
```

## ❌ 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

```js theme={null}
case "remove":
  return state.filter(item => item.id !== action.id);
```

## ❌ What’s Wrong

Fails if `action.id` undefined.

## 🤔 WHY

No validation.

## ✅ Fix

```js theme={null}
if (!action.id) return state;
```

## 🧠 Best Practice

Validate action payloads.

***

# 14. Using Reducer for Simple State

## 🐞 Buggy Code

```js theme={null}
const [state, dispatch] = useReducer(
  (s, a) => ({ value: a }),
  { value: 0 }
);
```

## ❌ What’s Wrong

Over-engineered.

## 🤔 WHY

No complex logic.

## ✅ Fix

Use `useState`.

## 🧠 Best Practice

Choose the right abstraction.

***

# 15. State Reset Bug

## 🐞 Buggy Code

```js theme={null}
case "reset":
  return initialState;
```

## ❌ What’s Wrong

`initialState` might be stale or mutated.

## 🤔 WHY

Shared reference issues.

## ✅ Fix

```js theme={null}
return { ...initialState };
```

## 🧠 Best Practice

Avoid shared mutable references.

***

# 16. Dispatch Inside Loop

## 🐞 Buggy Code

```js theme={null}
items.forEach(() => dispatch({ type: "update" }));
```

## ❌ 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

```js theme={null}
case "add":
  return [...state, action.payload.text];
```

## ❌ 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

```js theme={null}
{
  columns: { columnId: [cardIds] },
  cards: { cardId: { title, description } }
}
```

## ⚠️ 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

```js theme={null}
{
  messages: [],
  typingUsers: [],
  status: {}
}
```

## ⚠️ 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

```js theme={null}
{
  items: [],
  page: 1,
  status: "idle"
}
```

## ⚠️ 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

```js theme={null}
{ tabs: [], activeTabId }
```

## ⚠️ 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

```js theme={null}
{ filters, sort, results }
```

## ⚠️ 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

```js theme={null}
files: [{ id, progress, status }]
```

## ⚠️ 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:

```js theme={null}
dispatch({ type: "CHECKOUT_SUCCESS", payload })
```

### ❌ 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:

```js theme={null}
if (state.status === "loading" && action.type === "SUCCESS")
```

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:

```js theme={null}
return { ...state }; // even if unchanged
```

### ❌ 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:

```js theme={null}
dispatch({ type: "FETCH_START" });
```

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:

```js theme={null}
console.log(action)
```

### ❌ 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:

```js theme={null}
{ past: [], present: {}, future: [] }
```

### ❌ 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.

***

## 18. What is a common production bug related to stale closures with `useReducer`?

### 🔍 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.**

***
