React Lesson 15: Advanced Patterns
These patterns appear in professional React codebases. Understanding them separates junior from mid-level React developers.
useReducer for Complex State
import { useReducer } from "react";
const initialState = { count: 0, step: 1 };
function reducer(state, action) {
switch (action.type) {
case "INCREMENT": return { ...state, count: state.count + state.step };
case "DECREMENT": return { ...state, count: state.count - state.step };
case "SET_STEP": return { ...state, step: action.payload };
case "RESET": return initialState;
default: return state;
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<div>
<p>Count: {state.count} (step: {state.step})</p>
<button onClick={() => dispatch({ type: "INCREMENT" })}>+</button>
<button onClick={() => dispatch({ type: "DECREMENT" })}>-</button>
<input onChange={e => dispatch({ type: "SET_STEP", payload: Number(e.target.value) })} />
<button onClick={() => dispatch({ type: "RESET" })}>Reset</button>
</div>
);
}
useMemo and useCallback — Performance
import { useMemo, useCallback } from "react";
function ExpensiveList({ items, onSelect }) {
// useMemo: recompute only when items changes
const sorted = useMemo(() => {
return [...items].sort((a, b) => b.score - a.score);
}, [items]);
// useCallback: stable function reference (prevents child re-renders)
const handleClick = useCallback((id) => {
onSelect(id);
}, [onSelect]);
return (
<ul>
{sorted.map(item => (
<li key={item.id} onClick={() => handleClick(item.id)}>
{item.name}: {item.score}
</li>
))}
</ul>
);
}
You completed the React course!
What to build next:
- Next.js — Full-stack React with SSR and file-based routing
- TypeScript + React — Type-safe components
- React Query / SWR — Professional data fetching
🏋️ Practice Task
Build a complete mini app: a task manager with useReducer. Actions: ADD_TASK, TOGGLE_TASK, DELETE_TASK, FILTER(all/active/completed). Show filtered tasks. Add task count stats at the top.
💡 Hint: Reducer handles each action type. Filter with tasks.filter(t => filter === “all” || (filter === “active” ? !t.done : t.done)).