Intermediate
Async JavaScript, React fundamentals, and the daily UI surfaces — forms, lists, networking. The bar for mid-level coding rounds at most product companies.
Async JavaScript
Promises, async/await, the event loop, microtasks vs macrotasks, and the timing patterns — debounce, throttle, abort — that every real app uses.
Recommended prerequisites: javascript-core
Why interviewers ask
Async bugs are the most common production bugs. Interviewers want to know if you can reason about ordering, cancellation, and error propagation without hand-waving.
Real-world relevance
Every fetch, every animation frame, every queued task in your app routes through this model. Cancellation determines whether your search box leaks stale results into the UI.
Common interview patterns
- Trace execution order across sync, microtasks, and macrotasks
- Implement debounce and throttle from scratch
- Cancel a fetch with `AbortController` and the take-latest pattern
- Compose `Promise.all`, `allSettled`, `race`, and `any` correctly
Common mistakes
- Confusing microtask and macrotask ordering — Promises drain before setTimeout
- `await`-ing inside a loop when `Promise.all` would parallelize
- Forgetting unhandled rejections still fire even after a `.catch` is attached later
- Treating async/await as a magic sync conversion instead of syntactic sugar over Promises
Follow-up questions
- How would you implement `Promise.allSettled` from scratch?
- What happens to in-flight requests when a component unmounts mid-await?
- Compare debounce, throttle, and `requestAnimationFrame` for input handling
React Basics
Components, JSX, hooks, props, keys, conditional rendering, forms, refs, and the everyday patterns that make up a working React app.
Recommended prerequisites: javascript-core, async-javascript
Why interviewers ask
Most frontend roles are React roles. If you can't explain `useEffect`'s mental model, the interviewer will assume you can't ship cleanly.
Real-world relevance
Every feature ticket lives here. Picking the right hook, keying lists correctly, and colocating state are the decisions that compound into a maintainable codebase.
Common interview patterns
- Pick the right hook: state vs ref vs reducer vs effect
- Use stable keys to keep list reconciliation O(n)
- Lift state up — or colocate down — based on who reads it
- Build controlled forms with validation and field-level errors
Common mistakes
- Using array index as a key for a list that reorders
- Reaching for `useEffect` for derived state instead of computing during render
- Mutating state in place instead of creating a new reference
- Creating new object/array literals in JSX that thrash child memo
Follow-up questions
- Why does React batch state updates inside event handlers but not always inside Promises?
- When would you build a custom hook vs inline the logic?
- How does Suspense interact with data fetching libraries you have used?
Networking
HTTP, REST vs GraphQL, CORS, caching, cookies, WebSockets, SSE, and the lifecycle of a request from `fetch()` to the wire.
Recommended prerequisites: async-javascript
Why interviewers ask
Frontend bugs blamed on the backend are often network bugs. Interviewers want someone who can read a waterfall, debug a 401, and reason about cache headers.
Real-world relevance
Every API call you write inherits decisions about retries, cancellation, caching, and auth headers. Picking the wrong primitive (polling when SSE would work) shows up directly in cost and battery.
Common interview patterns
- Cancel stale requests with `AbortController` and the take-latest pattern
- Compare `Cache-Control`, `ETag`, and `stale-while-revalidate`
- Walk through a CORS preflight and what the browser actually sends
- Pick WebSocket, SSE, or long polling based on directionality and reconnection cost
Common mistakes
- Ignoring CORS until it breaks in prod — credentialed requests have stricter rules
- Not setting `SameSite` on auth cookies
- Polling for data that an SSE stream could push for free
- Treating fetch as a drop-in for Axios without porting interceptors and retry logic
Follow-up questions
- How would you implement `fetch` with timeout + retry + exponential backoff?
- Where would you put the AbortController in a Redux-Saga or React Query flow?
- What changes when you switch from HTTP/1.1 to HTTP/2 multiplexing?
TypeScript
Generics, narrowing, conditional types, utility types, and the discipline of typing a React app without `any`-escaping your way out.
Recommended prerequisites: javascript-core
Why interviewers ask
Most production codebases are TypeScript. Interviewers test whether you can model domain shapes correctly and whether you understand inference, not just syntax.
Real-world relevance
Strong types are a refactor multiplier. Library authors live and die by their generic constraints. Application engineers feel TS most in form schemas, API clients, and discriminated unions for UI state.
Common interview patterns
- Use discriminated unions to model `loading | success | error` UI state
- Pick between `interface` and `type` based on extension and declaration merging
- Build a generic helper with constraints and inferred return types
- Narrow with `in`, `typeof`, `instanceof`, and user-defined type guards
Common mistakes
- Reaching for `any` instead of `unknown` and narrowing
- Using enums where a string union would be lighter and more inferable
- Forgetting that interface declaration merging affects library typings globally
- Over-engineering generics that don't make any call site safer
Follow-up questions
- How would you type a `useFetch` hook that infers the response shape from the URL?
- What changes when you publish types for both ESM and CJS consumers?
- When does TS structural typing surprise you (e.g., excess property checks)?
State Management
Local state, lifted state, context, and external stores — Redux, Zustand, Recoil, MobX — with the tradeoffs that actually come up in code review.
Recommended prerequisites: react-basics
Why interviewers ask
Picking the wrong state tool is one of the most expensive architectural mistakes a team makes. Interviewers test whether you can justify the choice, not just name the libraries.
Real-world relevance
Server state, URL state, form state, and global UI state each want different tools. Conflating them is the root cause of half the 'why is this re-rendering' bugs in a real codebase.
Common interview patterns
- Separate server state (React Query/RTK Query) from client state (Zustand/Redux)
- Lift state only as far as the lowest common ancestor needs
- Use context for low-frequency values (theme, auth) and a store for high-frequency
- Model derived state as a selector, not a mirrored copy
Common mistakes
- Putting server response data in Redux when React Query would deduplicate it for free
- Subscribing to the whole store and re-rendering every consumer on any change
- Treating context as a state library — every consumer re-renders on any value change
- Building reducer logic for a value that one component owns
Follow-up questions
- When would you pick Zustand over Redux Toolkit on a new project?
- How does MobX's observable model differ from Redux's immutable reducer model?
- Where does URL state fit alongside in-memory state?