201 React interview questions with detailed answers, sorted from basic to advanced. Free to practice, with progress saved automatically.
React is a JavaScript library for building user interfaces out of components, with data flowing from parent to child through props. Topics include JSX, props and state, useState and useEffect, memoisation hooks like useMemo and useCallback, custom hooks, Context, forms and error handling, lifecycle, render optimisation patterns, and debugging scenarios.
and 63 more topics.
JSX is a syntax that lets you write HTML-like tags directly inside a JavaScript file. It is not a separate language — browsers do not understand JSX at all; Babel or SWC compiles it into function calls before the code runs. Think of JSX as…
JSX compiles into element-creation calls — React.createElement(type, props, ...children) in the classic transform, and jsx() from react/jsx-runtime since React 17. The return value is not a DOM node — it is a plain description object: { type: 'h1', props: { className: 'title', children: 'Hello' }…
Conditional rendering in React has no dedicated syntax — you use ordinary JavaScript expressions. Since JSX is just function calls, anything that produces a value can go inside curly braces. Three common approaches, simplest first: The third form exists because if is a statement, not…
A Fragment lets a component return several sibling elements without adding any wrapper node to the DOM. The full form is <React.Fragment; the shorthand is <...</. Two situations make Fragments mandatory rather than merely tidy: - HTML has parent–child constraints. <table will not take a…
key is how you tell React which item in a list is which across renders. Without it, React only has array position to compare — and position shifts every time you insert, remove or reorder. Picture a numbered row of seats. If the seats carry…
They differ in how names are written, what value you pass, how you stop default behavior, and where listeners are attached. Plain HTML JSX (React) --------- Attribute name Lowercase: onclick camelCase: onClick Value A string of code: "handleClick()" A function reference: {handleClick} Stopping default behavior…
Spread in JSX is the {...obj} syntax: it takes each key-value pair of obj and passes it as a separate prop. <Button {...btnProps} / is the same as writing out every prop in btnProps by hand. TextInput pulls label out to render it itself, collects…
React skips null, undefined, true and false; but the number 0 and strings are rendered. An empty string also shows nothing, but it is not in the skipped group — React still renders it, the result is just empty. That "skipped" list is exactly what…
Because JSX compiles to function calls, and a JavaScript function can only return one value. This is not a React rule — it is a constraint of the language itself. That second snippet is a plain JavaScript syntax error, unrelated to React. Hence the message…
props.children holds whatever you place between a component's opening and closing tags. It is an ordinary prop; the only difference is that JSX fills it in for you instead of you writing it out. These two forms are equivalent, which shows there is nothing mechanically…
React.memo is the replacement, but the two do not overlap exactly: PureComponent compares props and state, while memo compares props only. PureComponent is a base class you extend instead of Component; it implements shouldComponentUpdate for you as a shallow comparison over this.props and this.state. memo…
A Controlled Component is one where the value of form elements (like <input, <textarea, <select) is determined by React state. - Instead of the DOM holding the value itself, React state is the source of truth. - Every time the user types, an onChange event…
Component Composition is the technique of building complex components by combining or nesting simpler ones, instead of having one class component inherit (extends) from another as in object-oriented programming (OOP). Why React favors Composition: - Avoids deep inheritance trees: a subclass depends tightly on its…
A stateless component only takes props and renders; a stateful component keeps its own data that changes over time (state). Stateless Stateful --------- Where data comes from Only props from the parent props plus its own state (useState, useReducer) Same props give Always the same…
Compound Components is a pattern that splits a complex component into a group of small components sharing one piece of state. The parent holds the state and provides it through Context; the children read that Context, so consumers arrange the layout themselves without passing props…
In a React component's lifecycle, there are 3 main phases: 1. Mount: The moment when a component is created and inserted into the actual DOM for the first time. Corresponding Hook: useEffect with an empty dependency array []. The effect runs after React commits the…
A component only needs to return something React knows how to render — it does not have to be a JSX element. Since React 16 that list is wider than most people expect. The valid return types: - null, undefined, false, true — React skips…
Props are data a component receives from outside and must not modify; state is data the component owns and changes itself. The line is drawn by who owns the value. Think of a function: props are the parameters passed in, state is a local variable…
Lifting state up means moving state to the closest common parent when two or more components need the same data. Because data in React flows one way, downward, two siblings cannot talk to each other directly — the only place both can reach is their…
Immutability here means not modifying the object or array already in state, but creating a new one and passing it to the setter. The reason is concrete: React decides whether to re-render using Object.is on the old and new value — a reference comparison, not…
You must create a new copy at every level along the path to the value you are changing. React compares old and new state with Object.is, that is by reference — mutating in place and then calling the setter leaves React seeing "the same object"…
Derived state is a value you can compute from existing props or state, so it does not need to be stored as separate state. The common mistake is copying props into useState and using useEffect to keep the two in sync. The buggy version has…
Unidirectional data flow in React means: - Data flows in one direction: from the parent component down to the child via props. - A child component is not allowed to mutate the props it receives. Props belong to the parent, so the child only reads…
The closest match is useEffect(() = { ... }, []), but the two do not line up exactly: they fire at different moments, and in development Strict Mode they run a different number of times. componentDidMount runs exactly once, right after the component is inserted…
componentDidUpdate(prevProps, prevState) is called after every re-render except the initial mount, once the DOM has been updated. Compare prevProps/prevState against the current values to decide whether to perform a side effect. The classic use case: reload data when the userId prop changes. Why the condition…
The equivalent is the cleanup function returned from useEffect — but it runs more often than componentWillUnmount: before every re-run of the effect, not only on unmount. That difference is an improvement rather than a nuisance: it forces the teardown to sit next to the…
Lifecycle methods are functions React calls at each stage of a class component: mount (first appears on the page), update (props or state change) and unmount (removed). Real logs when mounting, updating props, then removing the component: Each method has its own job: - constructor:…
useState returns a pair: the current value and a function to change it. Calling the setter does not modify the variable in place — it schedules React to render the component again with the new value. The part beginners trip on: count is a constant…
The dependency array lists the values an effect depends on; React re-runs the effect when one of them changes. It is not a timer or a switch — it is a declaration that "this effect reads these things". Three forms, and they behave quite differently:…
Cleanup is the function you return from useEffect; React calls it before each re-run of the effect and once more when the component unmounts. It is not an "on exit" hook — it runs many times during a component's life. If delay changes, React calls…
Because useEffect treats the callback's return value as the cleanup function, and an async function always returns a Promise. React would hold that Promise and try to call it as a function on cleanup. The AbortController is not decoration. The effect can re-run before the…
An infinite loop happens when an effect updates the very thing it depends on. Set state → re-render → dependency changed → effect runs → set state. Nothing stops the chain. Three common causes and their fixes: 1. The effect writes state that is in…
A stale closure is a function that still sees values from an older render. It is not a React bug but ordinary JavaScript closure behavior: each render creates a fresh set of variables, and a function created in one render captures that render's values. The…
In development Strict Mode, React 18 deliberately runs effects twice: mount → cleanup → mount again. It is not a bug and it does not happen in production — it is a test of whether your effect cleans up properly. The reason: React is preparing…
No. Each component that calls the hook gets its own state — a custom hook shares logic, not data. The naming causes the confusion. "Sharing stateful logic" sounds like both components will see the same value, but a custom hook is just a function that…
A race condition happens when the effect re-runs before the previous request returns — the two responses arrive out of order and the stale one overwrites the fresh one. Nothing throws; the UI simply shows the wrong data. Picture a search box: the user types…
useContext is a hook that lets a component read a value from React Context without passing props through every level. You pass the object returned by createContext, and the hook returns the value from the nearest Provider above in the tree. Think of Context as…
useMemo caches a calculation's result between renders and recomputes only when a dependency changes (compared with Object.is). There are two reasons to use it: - Expensive calculations: filtering or sorting a large list that you don't want to redo on every render caused by unrelated…
useCallback caches the function itself between renders, so its reference stays the same while dependencies are unchanged. Every render, () = {...} creates a new function, so use it when passing a callback to a component wrapped in React.memo (a new function makes memo see…
useRef returns a { current } object that React keeps the same across every render. You can read and assign ref.current freely, and assigning it does not re-render the component. Those two properties give it two main uses: pointing at a DOM node, and storing…
Two rules: call hooks only at the top level of the function, and only from a function component or a custom hook. Both come from one implementation detail — React identifies hooks by call order, not by name. React keeps a list of hooks per…
Every component calling useContext re-renders when the Provider's value changes — even if it only reads an unrelated field. Context has no per-field subscription; it compares the whole value with Object.is. The most common mistake is building a new object inline in the Provider's JSX:…
The two memoize at different levels: - useMemo is a hook used inside a component to remember a computed value (a filtered array, an object…), recalculating only when its dependencies change. - React.memo wraps a whole component: if the new props equal the old ones,…
A custom hook is a regular JavaScript function whose name starts with use and which calls other hooks like useState or useEffect. It lets you pull stateful logic out of a component so several components can reuse it without copying code. useLocalStorage wraps three things:…
A simple test: does the logic need to call a hook (useState, useEffect, useContext...)? If yes, extract a custom hook; if it just takes input and returns output, write a plain utility function. formatPrice(1500000) always returns "1.500.000 đ" and remembers nothing between calls. It works…
useDebounce returns a delayed copy of value: the copy only updates once value has stayed unchanged for delay milliseconds. The classic use is a search box: call the API only when the user stops typing, instead of one request per keystroke. The mechanism is the…
usePrevious returns a variable's value from the previous render, typically to compare old and new (did the price go up or down, which id did the prop just change from). The classic implementation uses useRef: after each render the ref is updated with the current…
The Context API lets you share data (theme, language, auth, user info) across the component tree without passing props through every intermediate level (prop drilling). It has three parts: createContext, the Provider, and useContext. Trade-off: whenever value changes (compared with Object.is), every component calling useAuth…
Use Context when the data is something many components at deep, scattered levels need (theme, locale, the signed-in user), and the components in between only receive props to pass them down without using them. Passing props 2–3 levels doesn't need Context: props are explicit, and…
useParams is a hook that returns an object holding the URL params of the route that matches the current URL. A URL param is a dynamic part of the path, marked with a colon, such as :id. When you visit /users/42, the router matches the…
useNavigate returns a navigate function for changing routes from code, rather than having the user click a <Link. It replaces v5's useHistory. Common calls: - navigate('/path'): go to a new page, pushing an entry onto the browser history. - navigate('/path', { replace: true }): replace…
Nested routes use the <Outlet / component as the slot where child routes render. The parent route draws the shared layout and <Outlet / marks where child content appears. The router matches the URL against the route tree from the outside in: - /dashboard: matches…
Write a layout route that checks authentication, and put the protected pages under it as child routes. If the user is not logged in it redirects; otherwise it renders <Outlet / (the spot where the child route appears): - Protects a whole group of routes:…
The common approach is one context per group of data (auth, theme, cart), each with its own Provider and custom hook, then combining the Providers in an AppProviders component so the app's root file stays clean. Why split them: when a context value changes, every…
A query string is the part of a URL after ?, such as /products?tab=reviews&page=3. React Router reads and writes it through the useSearchParams hook, which returns a [searchParams, setSearchParams] pair like useState. searchParams is the browser's standard URLSearchParams. When filters, tab, and current page live…
An uncontrolled component is an input whose value is kept by the DOM. React does not store it in state and does not re-render on each keystroke; when you need the value (usually on submit) you read it from the DOM through a ref. A…
Formik is a form library for React: it holds field values, tracks which fields the user has interacted with (touched), runs validation, stores errors and handles the submitting state. Without it, every form needs hand-written useState per field, onChange handlers, an errors object and an…
The core difference is where form values live. Formik keeps every value in React state (controlled inputs), so each keystroke re-renders the whole form. React Hook Form (RHF) leaves values in the DOM (uncontrolled inputs) and reads them through refs, so typing does not re-render…
Form validation in React means checking user input before it is sent, then showing errors next to each field. The most basic approach is doing it by hand: keep values and errors in state and run a check function on submit. Submitting with the email…
An Error Boundary is a component that catches errors thrown while rendering the components below it and shows a fallback UI, instead of letting the whole tree unmount and leave a blank page. As of React 19 there is still no hook equivalent, so an…
An Error Boundary only catches errors that happen while React is rendering the subtree: errors during render, in lifecycle methods and in constructors of components below it. The reason: React calls those functions, so it can wrap them; code that runs outside rendering doesn't have…
Store the fields as an array of objects in state, each with a stable id created when the field is added. Adding, removing and editing all build a new array from the old one, then you render with map using that id as the key.…
React Hook Form (RHF) lets another library do the validation through the resolver option. The @hookform/resolvers package ships zodResolver: on each validation, RHF hands the form values to the Zod schema, then maps Zod's issues into formState.errors by field name. Submitting with the email "abc"…
React.memo is a HOC that memoizes a function component: it skips re-rendering if props haven't changed. Use it when the component is expensive to render and its props rarely change. Pair it with useCallback for function props for it to be effective. How it works:…
React.lazy lets you lazy load a component, downloading its JavaScript only when the component needs to render. Suspense shows a fallback UI while the component is loading. Together they are how you do code splitting in React and reduce the initial bundle size. What happens:…
Render props is a pattern where a component receives a prop that is a function returning JSX. The component owns the logic and state, and for the display it calls that function, passes the data in, and lets the parent decide what to render. MouseTracker…
Virtualization (also called windowing) means rendering only the items of a long list that are inside the visible area, instead of creating DOM for all of them. A 10,000-row list in a frame that shows 10 rows keeps only about a dozen elements in the…
Defining a component inside another component creates a new component type on every render. React compares types by reference: seeing a different type than last time, it doesn't update but unmounts the old one and mounts the new one, so state is lost, the old…
Changing a component's key makes React treat it as a different component: it unmounts the old instance, mounts a new one, and all state inside starts over from its initial value. This is the way React recommends to reset state from outside, with no useEffect…
The cleanup is the function an effect returns. It runs at two moments: (1) before each effect re-run when dependencies change, to tear down the old effect before the new one runs, and (2) when the component unmounts. What happens: when roomId changes, React does…
A custom hook is a function whose name starts with use and that calls other hooks (useState, useEffect...) inside. It lets components share stateful logic, while each component that calls the hook still gets its own state. Compared with the minimal version that only does…
On every render, { color: 'red' } or () = ... written in JSX is a new object/function with a different reference, even if the content is identical. React.memo compares each prop with its previous value using Object.is, that is, by reference, so it sees…
A common structure for medium and large projects is feature-based: each feature gets its own folder such as src/features/auth/ or src/features/dashboard/, holding that feature's components, hooks, services and types. Shared code lives in src/components/ for UI components, src/hooks/ for custom hooks, src/utils/ for helper functions,…
Continuous re-rendering is almost always a loop: rendering creates a new value, that value triggers setState, and setState causes another render. The classic case is an object created during render and used as a useEffect dependency. React compares dependencies by reference. Every render makes options…
Three signs tell them apart: it only happens in development, each mount produces exactly one extra run, and it stops when you remove <StrictMode. If any of those does not hold, the cause is elsewhere. The quick checks, in order: 1. Build for production and…
React only re-renders when the value passed to setState is a different reference from the current state (compared with Object.is). The most common cause is mutating an object or array in place and passing the same one back to setState. Calling addTodoBroken: the array now…
A memory leak in React is when a component has unmounted but something outside still holds a reference to it, so the browser cannot free the memory. The usual culprit is an Effect that registers something that outlives the component and never undoes it. Why…
For large forms, the best fit is React Hook Form. It keeps inputs uncontrolled: the value lives in the DOM and the library reads it through the ref that register attaches, so typing does not re-render any component. The form only re-renders when you subscribe…
CORS (Cross-Origin Resource Sharing) is the browser mechanism that decides whether JavaScript on one origin may read the response from another origin. An origin is scheme, domain and port, so an app on localhost:3000 calling an API on localhost:8080 is already cross-origin. For simple requests…
Hydration is the step where React in the browser attaches event handlers to HTML the server already rendered. To do that, React renders the component once more on the client and compares it with the HTML the server sent. When the two differ, that is…
useCallback keeps the same reference to a function across renders; useMemo caches an expensive computed value and only recomputes it when dependencies change. In fact, useCallback(fn, deps) is just useMemo(() = fn, deps). A real-world example: a product list page with a search box, sorting…
The 'missing dependency' warning comes from the ESLint rule react-hooks/exhaustive-deps (React itself doesn't report it at runtime). It shows up when you use a component variable (props, state, a function declared in the component) inside useEffect without listing it in the dependency array. The reason:…
A race condition in useEffect happens when the effect sends a request every time a dependency changes, but responses come back out of order. A slow old request that finishes last overwrites the result of the newer one. The fix is the effect's cleanup: it…
The difference is who holds the input's value. - Controlled: React state holds the value. On each keystroke, onChange calls setState, the component re-renders and the input shows the new value from state. Because React always knows the current value, you can validate, format or…
Prop drilling is having to pass props through many intermediate components that don't actually use them and only forward them. For example Page → Layout → Sidebar → Avatar: only Avatar needs user, yet Layout and Sidebar must also receive and pass user. As a…
key lets React identify which items changed, were added, or were removed in a list. On re-render, React matches new elements to old ones by key (the reconciliation step): the same key means the same item, so its DOM node and state are kept and…
Code splitting means breaking the JavaScript bundle into several smaller files (chunks); lazy loading means only downloading a component's chunk when it actually needs to render. The goal is a smaller initial bundle so the page shows up faster. How to implement it: React.lazy() together…
Infinite scroll has two things to optimize: loading more data at the right moment and not letting the DOM grow as the user scrolls past thousands of items. Loading more: put a "sentinel" element at the end of the list and watch it with IntersectionObserver.…
A correction first: memo is not a hook. memo and React.memo are the same function (importing { memo } from 'react' or calling React.memo is equivalent). The hook with a similar name is useMemo, which remembers a value inside a component, while memo wraps a…
A custom hook is a function whose name starts with use and that calls other hooks (useState, useEffect…) to pull stateful logic out of a component. Every component that calls it gets its own state; hooks share logic, not data. useForm keeps every field in…
An error boundary is a special component that catches JavaScript errors thrown while rendering its child tree and shows a fallback UI in place of the broken part, preventing a full app crash (blank screen). By default, an uncaught error during render makes React remove…
A compound component is a group of components that share implicit state: the parent holds the state and the children read it through Context. Consumers assemble the pieces in JSX, the way <select works with <option in HTML. Tabs holds the open tab, Tab reads…
A render prop is a pattern where a component accepts a function as a prop (or as children) and calls it with the data needed to render UI. A HOC (Higher-Order Component) is a function that takes a component and returns a new component with…
Suspense lets React pause rendering part of the component tree and show a fallback UI (e.g. a loading spinner) until that part is ready. A component "suspends" when it needs something that isn't there yet (a React.lazy JS chunk, or data still loading); React finds…
The four solve different needs; don't default to Redux. - Context API: not a state manager, just a way to pass a value without prop drilling (theme, locale, signed-in user). Every consumer re-renders when the value changes → bad for frequently-updated state. - Zustand: a…
Accessibility isn't an add-on added later; it is built in from the first line of the component. - Semantic HTML first: use <button, <nav, <main, <label instead of <div onClick. Native elements already ship with roles, keyboard handling and focus. ARIA only patches the gaps…
The common pitfall is typing the event as any or guessing the element type wrong. Event handlers — React ships generic types keyed by element and event kind. Use them instead of any: Tip: declaring the handler inline on the JSX prop lets TS infer…
RTL's philosophy: "test the way users use the app", not the internals. Query priority (best to last resort): 1. Accessible — getByRole (with name), getByLabelText, getByPlaceholderText, getByText. Mirrors how users and screen readers see the UI. 2. Semantic — getByAltText, getByTitle. 3. Test ID —…
An Error Boundary is a class component that catches errors during render of its subtree, showing a fallback UI instead of crashing the whole app (React unmounts the entire tree on an uncaught error). It catches via static getDerivedStateFromError (set state to render fallback) and…
A Custom Hook is a JavaScript function whose name starts with use and which calls other Hooks such as useState and useEffect inside. It is used to pull logic that uses Hooks out of a component so it can be reused in many places. UserList…
No. The warning means the Effect reads a reactive value (a prop, state, or something derived from them) without declaring it in the dependency array — so when that value changes, the Effect does not re-run and keeps using the value from an older render.…
The rule of thumb: if the value is rendered, use state; if it is only remembered between renders, use a ref. useState useRef --------- Assigning a value call the setter, triggers a re-render assign ref.current, no re-render Reading during render always fine should not be…
useId produces a unique, stable id string for wiring <label htmlFor to <input id, or for aria-describedby / aria-labelledby. Why not roll your own: - Math.random() yields different values on server and client → hydration mismatch, React warns and re-renders that subtree. - A global…
You do not need an isMounted flag. The "Can't perform a React state update on an unmounted component" warning was removed in React 18 because it produced more false positives than real findings: calling a setter on an unmounted component is simply a no-op and…
The callback passed to setInterval is created on the first render and never replaced. It closes over that render's count — always 0 — so every tick computes 0 + 1. Three fixes, pick by need: 1. Functional updater — the usual choice when the…
This signals an Effect mixing two kinds of logic: the reactive part (reconnect when roomId changes) and the non-reactive part (invoke the latest callback on each message). The parent creates a new onMessage every render, so the dependency keeps changing. Options in order of preference:…
Rule of thumb: Effects synchronize with external systems (WebSockets, DOM APIs, third-party analytics tied to a screen's lifecycle). Anything that happens because the user did something belongs in an event handler. Common mistake — submitting an order from an Effect when a state flag flips:…
The problem is a state shape that can represent impossible states. Three independent values create combinations the UI never defined, and every handler must remember to reset all three — miss one place and it drifts. Two fixes: 1. Collapse into one constrained state —…
A tidy useFetch solves only the easy half: call the API, set state. The hard parts appear as the feature grows: - Race conditions: two requests for the same key resolve out of order and a stale result overwrites a fresh one. You must abort…
useEffect runs after the browser has painted, so users see one frame of the tooltip in the wrong place before it jumps. useLayoutEffect runs after the DOM is updated but before paint, so measuring and repositioning land in the same frame. The "useLayoutEffect does nothing…
The ref-flag guard only hides the symptom. In StrictMode during development, React deliberately mounts → unmounts → remounts and runs setup/cleanup twice to surface Effects with missing cleanup. Production builds run it once. What it exposes: that Effect cannot recover from being re-run. That happens…
There are exactly three triggers: 1. Its own state changed — a setter was called with a value different from the current one (compared with Object.is). 2. Its parent re-rendered — by default every child re-renders too, even when its props are identical. This is…
No. An update goes through two distinct phases: - Render phase — React calls your component function, produces a new element tree, and diffs it against the previous one. This phase is pure computation, touches no DOM, and React may abort and restart it (concurrent…
A key is an item's identity across renders — React uses it to decide whether to keep or destroy that element's state and DOM node. An index is only a position, so when the list is reordered identities get assigned to the wrong items. Typical…
For DOM elements, effectively no. Creating a closure is very cheap, and React attaches listeners through delegation, so it does not add/remove a listener on every render. The problem only appears when that function is a prop of a memo-wrapped component: each parent render creates…
memo skips a render only when every prop is equal under a shallow comparison (Object.is per prop). Checklist, in order of frequency: 1. A prop is a new reference each time — object/array/function literals, style={{...}}, data={rows.filter(...)}. This is the number one cause. 2. The children…
The idea: an element is created where it is written, not where it is rendered. If the heavy component is created by a higher-level component that never changes, then the state-changing component receives it as the children prop — the reference stays identical, so React…
Before React 18, a render was synchronous and non-stoppable: once React started building the tree it ran to completion before handing control back to the browser. On a large tree the main thread is blocked, so typing or clicking feels delayed. Concurrent rendering lets React…
It flashes because the chunk loads very fast (tens of ms): React shows the fallback and immediately swaps in the real content, which reads as a jolt. Fixes, in the order to try them: 1. Mark the tab switch as a transition. During a transition…
From React 19, when a component renders a <title, <meta, or <link tag, React automatically hoists it into the document <head, even if the component sits deep in the tree. Things to know: - It works on the server (the tag ships inside the returned…
useFormStatus lets a component read the submission state of its nearest parent form without threading an isSubmitting prop down. It reads state through Context provided by the <form element itself, and Context only flows downward. Calling useFormStatus inside ContactForm — i.e. as a sibling of…
Both de-prioritize the expensive render so the input stays responsive. The difference is what you control. useTransition — when you own the setState call: useDeferredValue — when the value arrives as a prop and you cannot touch the setState: For a search box that owns…
Debounce delays by the clock; useDeferredValue delays by how busy the machine is. debounce 300ms useDeferredValue --------- Trigger 300ms with no new keystroke React is idle after urgent work Fast device still waits the full 300ms updates almost immediately Slow device 300ms and then a…
use() reads a value from a resource — currently a Promise or a Context. Why conditional calls are fine: hooks like useState must be called in a fixed order because React stores state in a list indexed by call position — skip one and everything…
A waterfall happens when a request only starts after the previous one finishes, even though they are independent. With Suspense the usual cause is that the child component only renders — and therefore only starts fetching — once the parent has its data. Fixes: 1.…
useOptimistic gives you a temporary copy of state to display while an action is running. Rollback is automatic, and that is the common follow-up: the optimistic value only lives for the duration of the running transition/action. When the action settles, whether it succeeds or fails,…
The split is clean: Suspense handles "data not ready yet" (a pending promise), an Error Boundary handles "broken" (a rejected promise or a throw during render). A rejected promise passes through Suspense and stops at the nearest Error Boundary above it. Putting the Error Boundary…
A hydration mismatch means the server HTML differs from the tree React builds on the client during the first render. From React 18 on, React discards that region's HTML and re-renders it on the client with a warning — slower, and possibly a visible flash.…
In a Server Component the component is an async function and you await directly — the data is already there when the HTML is produced. Key differences vs useEffect: - Network round trips: the client path is HTML → JS → hydrate → only then…
Cause: an await directly in the body of page.tsx blocks the entire output — the server cannot send a single byte until that query resolves. Fix: move the slow part into a child component wrapped in <Suspense. The fast shell streams immediately; the slow part…
invalidateQueries marks cache entries stale and refetches active queries — the data is guaranteed fresh from the server, at the cost of an extra round-trip. setQueryData writes the mutation result straight into the cache — no request at all, but you must guarantee what you…
Put a guard layer between the router and the page, and treat it as UX only — the server owns real authorization. Common shape: the session carries a permissions list, each route declares what it needs, the guard compares them. Three follow-ups interviewers usually add:…
Principle: one source of truth for the whole wizard; each step is just a view onto it. State. Keep all values in the parent form (react-hook-form FormProvider, or a reducer) and let each step read/write through context. If every step owns its own state, going…
The standard model is an array of objects in form state, one element per row, validated by an array schema so errors bind to the right index. The classic bug is key={i}. Removing a middle row makes React treat later rows as "same key, new…
Three layers: fewer requests, no out-of-order results, keyboard control. Fewer requests. Debounce ~250–300ms and skip very short terms (< 2 chars). With a per-term cache, retyping an earlier term needs no request at all. Out-of-order results (race condition). Typing "ha" then "han": the slower "ha"…
At minimum four states: loading, has data, empty, error. Forgetting the empty state is the most common miss — an empty list looks exactly like a silent failure. How to present each: - Loading: use a skeleton shaped like the incoming content for lists/cards, a…
Make the current language a piece of application state, not a value read once at startup. When the state changes React re-renders and every string is looked up again. The code above works in an app that renders entirely on the client (Vite, Create React…
Split by data source: the list of cart items is server state (the backend owns it, the client only caches it), while the selected items and the quantity being typed are UI state. Totals and item counts are not stored in state — they are…
A class component is declared with class extends React.Component, keeps state in this.state and handles side effects through lifecycle methods; a function component is a plain function that uses hooks (useState, useEffect) for state and side effects. Since hooks arrived (React 16.8, early 2019) new…
React is a JavaScript library for building UIs from components: you describe what the UI looks like for the current state, and React updates the DOM to match. Compared with plain JavaScript, the main win is not writing "find this element, change that text" instructions…
Atomic Design is Brad Frost's methodology that splits UI into 5 levels from small to large, borrowing a chemistry metaphor: atoms combine into molecules, molecules into larger structures. The goal is to build a reusable component system instead of designing each page in isolation. Level…