Week 2 — Managing State, Escape Hatches & Data
Days 1–2 build React state and Effects fluency; days 3–5 apply Redux Toolkit and TanStack Query to Nest-backed data — then ship a Todo mini-project (RTK + Query).
- 1. Reacting to input with stateOpen
Controlled inputs, change events, and form submission.
- 2. Choosing the state structureOpen
Avoiding redundancy, duplication, and deeply nested state.
- 3. Sharing state between componentsOpen
Single source of truth, controlled children, and callbacks.
- 4. Preserving and resetting stateOpen
Tree position, keys, remounting, and intentional resets.
- 5. Extracting state logic into a reducerOpen
useReducer, actions, and pure transition logic.
- 6. Passing data deeply with contextOpen
createContext, providers, consumers, and focused context values.
- 7. Scaling state with reducer and contextOpen
Provider composition, dispatch, and predictable actions.
- 8. Referencing values with refsOpen
useRef, mutable current, and state versus refs.
- 9. Manipulating the DOM with refsOpen
Ref assignment, focus management, and avoiding DOM conflicts.
- 10. Synchronizing with EffectsOpen
useEffect setup, dependencies, and cleanup.
- 11. You might not need an EffectOpen
Derived state, memoization only when needed, and event logic.
- 12. Lifecycle of reactive EffectsOpen
Setup, cleanup, dependency changes, and unmount.
- 13. Separating events from EffectsOpen
Causal reasoning, handlers, and reactive synchronization.
- 14. Removing Effect dependenciesOpen
Dependency honesty, stable values, and avoiding stale closures.
- 15. Reusing logic with custom HooksOpen
Hook composition, inputs, returned APIs, and rules of Hooks.
- 16. Caching calculations with useMemoOpen
Memoized derived values, dependency lists, and when a plain calculation during render is enough.
- 17. Caching functions with useCallbackOpen
Stable callbacks, memoized children, Effect dependencies, and avoiding needless wrapping.
- 18. Redux Toolkit — official tutorial pathOpen
This course lesson mirrors https://redux-toolkit.js.org/tutorials/overview and the Quick Start steps, then maps them onto this monorepo (Next + TypeScript + Nest).
- 19. RTK Essentials practice: client draftsOpen
This is our Redux Essentials-style lab: use RTK for a composer draft after Quick Start, then ship it in Week 4 Notes projects.
- 20. TanStack Query fundamentalsOpen
useQuery, useMutation, query keys, and invalidation.
- 21. Axios, Nest, and cookiesOpen
Axios instances, withCredentials, CORS, and 401 handling.
- 22. RTK Query vs TanStack Query (and when to use which)Open
Cover the RTK Query APIs from Getting Started, then the ownership rule for this course.
End-of-week mini-project · practice only
Todo app (RTK + Query)
Ship a Todo UI where unfinished draft/filter state lives in Redux Toolkit and the todo list comes from TanStack Query, with debounced search and memoized rows.
Definition
A client that separates unfinished composer/chrome state (RTK) from server-backed todo rows (TanStack Query + Axios cookies), applying the Week 2 escape hatches — reducers, refs, Effects, custom hooks, and memoization — with the course ownership rule.
In simpler words
Type a draft in Redux. When you save, Query talks to Nest (or a mock). Never store the Nest list in Redux, and don’t refetch on every keystroke.
Concepts covered this week
- Reacting to input with state
- A controlled composer input drives the new-todo draft.
- Choosing the state structure
- Store only draft, filter, and selection — derive the visible list instead of duplicating it.
- Sharing & lifting state
- The toolbar filter and the list read the same shared state.
- Preserving & resetting state
- Editing a todo remounts the form via a key so stale text does not leak in.
- Extracting logic into a reducer
- createSlice reducers own the draft/selection/filter transitions.
- Context & scaling reducer + context
- The RTK Provider replaces hand-rolled context; a tiny theme context shows the pattern it improves on.
- Referencing values with refs
- A ref focuses the input after add; another ref holds a debounce timer id that must not cause renders.
- Manipulating the DOM with refs
- A DOM ref scrolls a newly added todo into view.
- Synchronizing with Effects / you might not need an Effect
- The filtered list is derived in render; an Effect is used only for a real subscription like online status.
- Effect lifecycle & removing dependencies
- A debounced-search Effect cleans up its timer and lists honest dependencies.
- Separating events from Effects
- Saving a todo is a click handler, not an Effect reacting to state.
- Reusing logic with custom Hooks
- useDebouncedValue and useOnlineStatus package the Effect logic.
- Caching with useMemo / useCallback
- Memoize the filtered list and pass stable handlers to memoized rows.
- Redux Toolkit & client drafts
- configureStore + a slice own draft text, selected id, and filter chrome.
- TanStack Query fundamentals
- useQuery loads the list; useMutation creates/toggles/deletes and invalidates.
- Axios, Nest & cookies
- Axios withCredentials sends the cookie JWT; no token in localStorage.
- RTK Query vs TanStack Query
- Apply the ownership rule: server rows in Query, unfinished UI state in RTK.
Deliverables
- configureStore + createSlice for draft text, selected id, and filter chrome
- Typed useAppDispatch/useAppSelector; RTK Provider on the client tree
- useQuery list + useMutation create/toggle/delete with invalidateQueries on success
- A useDebouncedValue custom hook so search does not refetch every keystroke; memoized filtered list + rows
- Axios withCredentials for cookie JWT; honest loading/empty/error UI with submit disabled while pending
Build guide
- Model client stateCreate a slice for draft text, selection, and filter; derive the visible list rather than storing it.
- Wire the storeAdd configureStore, typed hooks, and the Provider on the client tree; watch draft updates in Redux DevTools.
- Load the list with QueryFetch todos with useQuery through an Axios client that sends credentials.
- Mutate + invalidatecreate/toggle/delete via useMutation; on success clear the draft and invalidateQueries.
- Search without over-fetchingExtract useDebouncedValue; keep filterDraft in RTK and only apply it after the debounce.
- Optimize rendersMemoize the filtered list and row handlers so typing does not re-render every row.
- Handle the edgesShow distinct loading/empty/error states and disable submit while a mutation is pending.
Acceptance checklist
- [ ] RTK owns draft + selection + filter (not the server todos array)
- [ ] Query owns the list; onSuccess clears draft + invalidateQueries
- [ ] Search is debounced via a custom hook; typing does not refetch each keystroke
- [ ] Filtered list + row handlers are memoized
- [ ] Cookie credentials path works (or documented stub)
- [ ] Empty ≠ loading; mutation errors visible on the form; no JWT in localStorageStretch goals
- Add an optimistic toggle with rollback on mutation error.
- Persist the filter/selection to the URL query string.
- Add drag-to-reorder using a ref-backed pointer handler.
Tips
- Open /examples/data for the live Query + Axios lab; skim /examples/state for the RTK-vs-Query ownership table.
- If the Nest Todos API is not ready, mock the HTTP contract first, then swap the queryFn.
- Reuse the same ownership table you will need for the Week 4 Notes UI.
- Typing should update filterDraft (RTK), not appliedFilter — only the debounced value refetches.