React interview revision notes
UI library: components, hooks, state. Written for developers preparing for an interview who want to refresh their React fast. Free, no sign-up.
21 topics in these notes
- What is React?
- Components (functional vs class)
- JSX
- Props
- State (useState)
- Event handling
- Conditional rendering
- Lists & keys
- useEffect
- useRef
- useCallback & useMemo
- Custom hooks
- Context API
- Lifting state up
- Controlled vs uncontrolled
- Forms in React
- React Router (basics)
- Virtual DOM & reconciliation
- React.memo & performance
- Error boundaries
- Portals
What is React?
Simple real-life example (Understand first — very important for understanding)
- Think of a web page as made of building blocks: a header block, a list block, a form block. Each block can show different content but works the same way.
- React is a library that lets you build the UI from such blocks (components), keep them in sync with data, and update only what changed.
- Real-world idea: build the screen from small, reusable pieces that react to data and user actions.
Real-world idea: UI as reusable components that update when data changes. React helps you build and maintain complex interfaces.
Technical definition
- React is a JavaScript library for building user interfaces. Component-based: UI is built from small, reusable components.
- Declarative: you describe what the UI should look like for a given state; React updates the DOM to match. Uses a Virtual DOM for efficient updates.
- Developed by Meta; used with React Native for mobile. Often used with a bundler (Vite, Create React App) and state/routing libraries.
Simple practical example
Declarative: you describe what the UI should look like for a given state; React updates the DOM to match.
Code example
function App() {
return <h1>Hello, World!</h1>;
}
ReactDOM.createRoot(document.getElementById('root')).render(<App />);Why it matters
Most front-end roles expect React knowledge. "What is React?" and "Why use it?" are opening questions.
Interview tip
"React is a library for building UIs with components. Declarative; Virtual DOM for performance; unidirectional data flow."
Components (functional vs class)
Simple real-life example (Understand first — very important for understanding)
- Like LEGO pieces: each piece (button, card, list item) is a component; you combine them to build the full page.
- A component is a function or class that returns what to show (JSX); you can reuse it with different data (props).
- Breaking the UI into components keeps code clear and makes it easy to change one piece without touching the rest.
Real-world idea: one piece of UI, reusable everywhere. Components are the building blocks of a React app.
Technical definition
- Functional components: plain functions that return JSX. Preferred in modern React; use Hooks for state and effects.
- Class components: ES6 classes extending
React.Component; usethis.stateand lifecycle methods. Legacy; avoid for new code. - Components can be composed: use one component inside another. Props flow down from parent to child.
Simple practical example
Class components: ES6 classes extending React.
Code example
function Welcome({ name }) {
return <p>Hello, {name}</p>;
}
// Usage: <Welcome name="Alice" />Why it matters
"Functional vs class?" — always say functional + Hooks for new code. Know that class components still exist in older codebases.
Interview tip
"Prefer functional components with Hooks. Class components use this.state and lifecycle; functional use useState/useEffect."
JSX
Simple real-life example (Understand first — very important for understanding)
- Like writing HTML inside JavaScript: you see tags (e.g. <div>, <button>) but they become function calls that create elements.
- JSX lets you mix structure (tags), expressions in curly braces, and logic so the UI and data stay in one place.
- It's not real HTML; it's a syntax that React turns into the actual DOM updates.
Real-world idea: describe the UI in a familiar tag-like syntax. JSX is the way you write component output in React.
Technical definition
- JSX is syntax that looks like HTML inside JavaScript. It compiles to
React.createElement()calls. One parent element per return (or use Fragment<></>). - Use
{expression}for dynamic values.classNameinstead ofclass;htmlForinstead offor. camelCase for event handlers:onClick,onChange. - JSX prevents injection by default: values are escaped. Dangerously setting HTML:
dangerouslySetInnerHTML(avoid unless necessary).
Simple practical example
Use {expression} for dynamic values.
Code example
const name = "Alice";
return (
<div className="card">
<h1>{name}</h1>
<button onClick={() => alert('hi')}>Click</button>
</div>
);Why it matters
Every React component uses JSX (or equivalent). Knowing className vs class and expression syntax is basic.
Interview tip
"JSX compiles to createElement. Use className, camelCase events; expressions in curly braces. One root or Fragment."
Props
Simple real-life example (Understand first — very important for understanding)
- Like passing instructions to a component: "Here is the title," "Here is the list of items." The parent gives, the child receives.
- Props are read-only; the child cannot change them. They flow down from parent to child.
- Use props to customize how a component looks or what data it shows so the same component can be reused with different content.
Real-world idea: pass data and settings into a component. Props are how parents configure and feed data to children.
Technical definition
- Props are read-only inputs passed from parent to child. Like function arguments. Access as
props.nameor destructure:function Child({ name }). - Props are immutable in the child — do not modify them. Parent owns the data; child displays or notifies via callbacks passed as props.
childrenis a special prop: content between opening and closing tags.props.childrencan be a single element, array, or nothing.
Simple practical example
Props are immutable in the child — do not modify them.
Code example
function Card({ title, children }) {
return (
<div>
<h2>{title}</h2>
{children}
</div>
);
}Why it matters
Data flow in React is unidirectional: parent → child via props. "How do you pass data?" — props. "Can child change props?" — no.
Interview tip
"Props are read-only, passed parent to child. Use destructuring. children for content between tags."
State (useState)
Simple real-life example (Understand first — very important for understanding)
- Like a component's memory: "Is the modal open?" "What did the user type?" State holds values that can change and that the component cares about.
- When state changes, React re-renders that part of the UI so the screen stays in sync with the data.
- State is private to the component; only that component can update it (unless you lift it up or use context).
Real-world idea: data that can change and that drives what the component shows. State is the component's own memory.
Technical definition
- State is data that can change over time and triggers re-renders when updated. In functional components:
const [value, setValue] = useState(initial). setValue(newValue)orsetValue(prev => prev + 1)for updates. State updates are asynchronous and batched; use functional updates when new state depends on previous.- Each component instance has its own state. Lifting state up = move state to a common parent when siblings need to share it.
Simple practical example
setValue(newValue) or setValue(prev => prev + 1) for updates.
Code example
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(c => c + 1)}>
Count: {count}
</button>
);Why it matters
useState is the first Hook you use. "How do you add state?" — useState. Know when to use functional updates (e.g. increment).
Interview tip
"useState(initial) returns [value, setter]. Use setter with function when new state depends on previous. Updates are batched."
Event handling
Simple real-life example (Understand first — very important for understanding)
- Like a button that says "when I'm clicked, do this": the user does something (click, type, submit), and you run a function in response.
- You pass a function (e.g. onClick, onChange) to the element; React calls it when the event happens, often to update state or call an API.
- Handlers are where you connect user actions to your app's behavior.
Real-world idea: respond to user actions. Event handlers connect clicks, input, and form submits to your logic and state.
Technical definition
- React uses synthetic events: same interface as DOM events but cross-browser. Pass a function as
onClick,onChange, etc., not a string. - Handler receives the event object. Call
e.preventDefault()to prevent default (e.g. form submit). Don't needaddEventListener— declare in JSX. - To pass extra arguments:
onClick={() => handleClick(id)}oronClick={handleClick.bind(null, id)}. Arrow avoids binding in constructor (class) or re-binding.
Simple practical example
Handler receives the event object.
Code example
<input onChange={(e) => setName(e.target.value)} />
<button onClick={() => submit(id)}>Submit</button>Why it matters
Event handlers are in every interactive component. Know camelCase, passing args, and that React pools events (don't use e async).
Interview tip
"Use camelCase (onClick). Pass function, not call. Synthetic events; e.persist() if you need e in async (rare)."
Conditional rendering
Simple real-life example (Understand first — very important for understanding)
- Like showing different things depending on the situation: "If logged in, show the dashboard; otherwise show the login form."
- You use conditions (if/else, ternary, &&) in your JSX or before return to decide what to render.
- Conditional rendering keeps the UI in sync with state and permissions.
Real-world idea: show one thing or another based on data or state. Conditional rendering is how you switch between views or messages.
Technical definition
- Use JavaScript:
{condition && <Component />}or{condition ? <A /> : <B />}. Early return in component:if (!user) return null;. - Falsy gotcha:
count && <span>...</span>renders0when count is 0. Prefercount > 0 && ...or ternary. - Can assign JSX to a variable and return it, or use IIFE for complex logic (usually better to split into subcomponents).
Simple practical example
Falsy gotcha: count && <span>.
Code example
{isLoading ? <Spinner /> : <List items={items} />}
{error && <p className="error">{error}</p>}Why it matters
Conditional UI is everywhere (loading, error, empty state). Know && and ternary; avoid rendering 0 by mistake.
Interview tip
"Use condition && JSX or ternary. Watch out: 0 is falsy so count && ... can show 0."
Lists & keys
Simple real-life example (Understand first — very important for understanding)
- Like a roster: you have an array of items and you want to show one block per item (e.g. one row per user).
- You map over the array and return a component for each item; React needs a stable key on each item so it can track which row is which when the list changes.
- Keys should be unique among siblings and stable (e.g. id), not the array index, when the list can be reordered or filtered.
Real-world idea: render one component per item in a list. Keys help React update the list efficiently when items change.
Technical definition
- Render lists with
array.map()returning JSX. Each top-level element in the list should have a unique key prop (e.g.key={item.id}). - Keys help React identify which items changed/added/removed for efficient reconciliation. Use stable, unique IDs — avoid array index as key when list can reorder or change.
- Keys must be on the element you return from map, not necessarily on a child. Keys are not passed as props to the component.
Simple practical example
Keys help React identify which items changed/added/removed for efficient reconciliation.
Code example
{items.map(item => (
<li key={item.id}>{item.name}</li>
))}Why it matters
"Why keys?" and "Can we use index as key?" — common. Use id when possible; index only for static lists that don't reorder.
Interview tip
"Keys must be unique among siblings; stable identity. Prefer id over index to avoid bugs when list order changes."
useEffect
Simple real-life example (Understand first — very important for understanding)
- Like a side effect that runs after the component is on screen: "When this component mounts, fetch data" or "When this value changes, sync with the server."
- useEffect runs after render; you list which values it depends on so it runs again when those change (or once on mount if the list is empty).
- Use it for fetching, subscriptions, or any action that should happen in response to being on screen or to a change in props/state.
Real-world idea: do something after render or when something changes. useEffect is for side effects like fetching or subscribing.
Technical definition
useEffect(() => { ... }, [deps])runs after render. No deps array = run after every render. Empty array[]= run once (mount). Array with values = run when those values change.- Return a cleanup function to run on unmount or before re-running effect:
return () => clearInterval(id);. Use for subscriptions, timers, listeners. - Common mistakes: missing deps (stale closure), deps that change every render (infinite loop), forgetting cleanup (memory leaks).
Simple practical example
Return a cleanup function to run on unmount or before re-running effect: return () => clearInterval(id);.
Code example
useEffect(() => {
const sub = api.subscribe(id, setData);
return () => sub.unsubscribe();
}, [id]);Why it matters
useEffect is for side effects (fetch, subscribe, DOM). "When does useEffect run?" and dependency array are standard questions.
Interview tip
"useEffect runs after paint. Deps: none = every render, [] = mount only, [a,b] = when a or b change. Return cleanup for subscriptions."
useRef
Simple real-life example (Understand first — very important for understanding)
- Like a sticky note that doesn't trigger a re-render: you want to keep a value (e.g. a DOM node, a timer ID) across renders without the component re-rendering when it changes.
- useRef gives you a box that persists; changing .current does not cause a re-render. Use for DOM refs, timers, or keeping a previous value.
- Refs are for "remember this" without making the UI depend on it.
Real-world idea: hold a value that doesn't drive the UI. useRef is for DOM refs, timers, and similar storage.
Technical definition
useRef(initialValue)returns a mutable object{ current: value }that persists across re-renders and does not trigger re-render when updated.- Use for: DOM reference (
ref={inputRef}, theninputRef.current.focus()), storing previous value, or any mutable value that shouldn't cause re-render. - Refs are for "escape hatch" — don't overuse for state that should drive UI; use useState instead.
Simple practical example
Use for: DOM reference (ref={inputRef}, then inputRef.
Code example
const inputRef = useRef(null);
useEffect(() => inputRef.current?.focus(), []);
return <input ref={inputRef} />;Why it matters
"When do you use useRef vs useState?" — ref when you need to hold something without re-render (DOM node, interval ID, prev value).
Interview tip
"useRef: mutable .current, no re-render. Use for DOM refs, timers, or keeping previous value. useState when UI must update."
useCallback & useMemo
Simple real-life example (Understand first — very important for understanding)
- Like avoiding unnecessary work: if a heavy computation or a callback only depends on certain inputs, you can memoize so it's only redone when those inputs change.
- useCallback memoizes a function; useMemo memoizes a value. Both take a dependency array so React knows when to recompute.
- Use them when you've measured and found unnecessary re-renders or repeated work; don't overuse.
Real-world idea: skip recomputing when inputs haven't changed. useCallback and useMemo optimize when needed.
Technical definition
useCallback(fn, deps)returns a memoized function — same reference until deps change. Use when passing callbacks to optimized children (React.memo) to avoid unnecessary re-renders.useMemo(() => compute(a, b), [a, b])returns a memoized value. Use for expensive computations that depend on props/state. Don't use for every small calc — only when it helps.- Both depend on dependency array. Wrong deps = stale closures or unnecessary recalc. Don't over-optimize; measure first.
Simple practical example
useMemo(() => compute(a, b), [a, b]) returns a memoized value.
Code example
const handleClick = useCallback(() => doSomething(id), [id]);
const sorted = useMemo(() => items.slice().sort(...), [items]);Why it matters
"What's the difference between useCallback and useMemo?" — callback memoizes function, memo memoizes value. Used with React.memo for performance.
Interview tip
"useCallback = memoized function; useMemo = memoized value. Use when passing to memo'd children or expensive computation."
Custom hooks
Simple real-life example (Understand first — very important for understanding)
- Like extracting a repeated pattern: if several components do the same thing (e.g. fetch data, track window size), put that logic in a function that uses hooks.
- A custom hook is a function whose name starts with use and that can call other hooks; it lets you reuse stateful logic without duplicating code.
- Same rules as hooks: call at the top level, only from React code (components or other hooks).
Real-world idea: reuse state and effects in a function. Custom hooks keep components simple and logic reusable.
Technical definition
- Custom hook = function whose name starts with
useand that can call other Hooks. Encapsulates reusable stateful logic (e.g. form field, fetch, subscription). - Each call to the hook gets its own state (Hooks are per-component instance). Share logic without sharing state unless you lift it or use context.
- Examples:
useLocalStorage,useDebounce,useFetch. Keep them focused and testable.
Simple practical example
Each call to the hook gets its own state (Hooks are per-component instance).
Code example
function useCounter(initial = 0) {
const [count, setCount] = useState(initial);
const inc = () => setCount(c => c + 1);
return [count, inc];
}Why it matters
"What is a custom hook?" — reuse logic that uses Hooks. Demonstrates understanding of rules of Hooks (only call at top level, from React functions).
Interview tip
"Custom hook: function starting with 'use' that uses other Hooks. Reuse stateful logic; each component gets its own state."
Context API
Simple real-life example (Understand first — very important for understanding)
- Like a notice board that many components can read without passing props through every level: theme, current user, language.
- You create a context, provide a value at the top, and any component in the tree can consume it without prop drilling.
- Use for data that is "global" to a part of the tree; for frequently changing data, consider state management or composition.
Real-world idea: share data through the tree without passing props. Context is for theme, user, or other widely needed data.
Technical definition
- Context provides a way to pass data through the tree without prop drilling.
createContext(default),Providerwraps tree, consumers useuseContext(MyContext)orConsumer. - Use for theme, locale, auth user — data that many components need. Avoid putting frequently changing data in one big context (causes wide re-renders); split contexts or use state library.
- Context does not replace Redux for complex global state; it's for "read-heavy" shared data. Value change re-renders all consumers.
Simple practical example
Use for theme, locale, auth user — data that many components need.
Code example
const ThemeContext = createContext('light');
// Provider: <ThemeContext.Provider value="dark">...</ThemeContext.Provider>
// Consumer: const theme = useContext(ThemeContext);Why it matters
"How do you avoid prop drilling?" — Context. "When not to use Context?" — when value changes often and tree is deep (consider state library or composition).
Interview tip
"Context: createContext, Provider, useContext. Good for theme/auth/locale. Splitting context or memoizing value reduces re-renders."
Lifting state up
Simple real-life example (Understand first — very important for understanding)
- When two components need the same data (e.g. two siblings both need the selected item), that data can't live in just one of them.
- You "lift" the state up to the nearest common parent; the parent holds the state and passes it down (and a setter) so both children stay in sync.
- Lifting state keeps a single source of truth when multiple components depend on the same value.
Real-world idea: put shared state in the common parent. Lifting state keeps siblings in sync with one source of truth.
Technical definition
- When two or more components need to share state, move that state to their common ancestor. Pass state down as props and pass updater (setState or callback) so children can notify changes.
- Single source of truth: one place owns the state; others receive and optionally request updates. Keeps data flow predictable.
- If lifting makes the tree heavy (too many props through middle components), consider Context or a state library.
Simple practical example
Single source of truth: one place owns the state; others receive and optionally request updates.
Code example
function Parent() {
const [value, setValue] = useState('');
return (
<>
<ChildA value={value} />
<ChildB onChange={setValue} />
</>
);
}Why it matters
"How do siblings share state?" — lift state to parent. Very common pattern in forms and filters.
Interview tip
"Lift state to the closest common parent. Pass state down, pass setter or callback so children can update."
Controlled vs uncontrolled
Simple real-life example (Understand first — very important for understanding)
- Controlled: the input's value comes from state; you update state on change, so React fully controls what is shown and what happens.
- Uncontrolled: the input keeps its own value in the DOM; you read it when you need it (e.g. on submit) via a ref.
- Controlled is the usual React way (single source of truth); uncontrolled is simpler when you only need the value at one moment.
Real-world idea: who owns the input value. Controlled = React state; uncontrolled = DOM, read when needed.
Technical definition
- Controlled: input value is driven by React state (
value={name}+onChange). Single source of truth; easy to validate and transform. - Uncontrolled: input keeps its own state in the DOM; you read it via ref when needed (e.g.
ref.current.valueon submit). Simpler for one-off forms or file input. - React recommends controlled for most form inputs. Uncontrolled is fine for file inputs or when integrating with non-React code.
Simple practical example
Uncontrolled: input keeps its own state in the DOM; you read it via ref when needed (e.
Code example
// Controlled
const [name, setName] = useState('');
<input value={name} onChange={e => setName(e.target.value)} />
// Uncontrolled
const ref = useRef();
<input ref={ref} /> // ref.current.value when neededWhy it matters
"Controlled vs uncontrolled component?" — controlled = value from state; uncontrolled = DOM holds value, read via ref.
Interview tip
"Controlled: value + onChange from state. Uncontrolled: ref to read DOM value. Prefer controlled for validation and consistency."
Forms in React
Simple real-life example (Understand first — very important for understanding)
- Like a paper form: user fills fields, you validate (required, format), and on submit you collect all values and send them (e.g. to an API).
- In React you often keep form fields in state (controlled), validate on change or submit, and show errors next to fields or at the top.
- Handling submit (preventDefault), validation, and error state keeps forms predictable and user-friendly.
Real-world idea: collect and validate user input, then submit. Forms in React use state, handlers, and validation.
Technical definition
- Controlled approach: one state per field (or one object).
onChangeupdates state;onSubmiton form prevents default and handles submit. Validate on submit or on blur. - For many fields:
useState({ name: '', email: '' })andsetForm(f => ({ ...f, [e.target.name]: e.target.value })). Or use a form library (React Hook Form, Formik). - Checkboxes/radios: value and checked; select: value on <select> and option values. Handle multi-select with array in state.
Simple practical example
For many fields: useState({ name: '', email: '' }) and setForm(f => ({ .
Code example
<form onSubmit={e => { e.preventDefault(); submit(form); }}>
<input name="email" value={form.email} onChange={handleChange} />
<button type="submit">Submit</button>
</form>Why it matters
Forms are common. Know controlled pattern, preventDefault on submit, and when to use a form library for complex forms.
Interview tip
"Controlled inputs, one state object for form, preventDefault in onSubmit. For complex forms consider React Hook Form."
React Router (basics)
Simple real-life example (Understand first — very important for understanding)
- Like different pages in an app: URL changes (e.g. /about, /users/5), and the app shows the right component for that URL.
- A router library (e.g. React Router) maps URLs to components and keeps the browser URL in sync with what's on screen.
- So you get bookmarkable, shareable links and back/forward navigation without full page reloads.
Real-world idea: one app, many URLs. A router maps the URL to the right component and keeps navigation in sync.
Technical definition
- React Router provides declarative routing:
BrowserRouter,Routes,Route path="..." element={<Page />}".Link to="..."for navigation without full reload. useParams()for route params (e.g./user/:id).useNavigate()for programmatic navigation.useLocation()for current path/search.- Nested routes:
Routewithpathand childRoutes; useOutletto render child route component.
Simple practical example
useParams() for route params (e.
Code example
<Routes>
<Route path="/" element={<Home />} />
<Route path="/user/:id" element={<User />} />
</Routes>
// In User: const { id } = useParams();Why it matters
SPAs need routing. "How do you do routing in React?" — React Router; know Link, Route, useParams, useNavigate.
Interview tip
"React Router: BrowserRouter, Routes, Route, Link. useParams for :id, useNavigate for programmatic nav, Outlet for nested routes."
Virtual DOM & reconciliation
Simple real-life example (Understand first — very important for understanding)
- Like making a quick sketch of what the page should look like, then comparing it to the last sketch and only changing what's different.
- React keeps a lightweight copy of the DOM (virtual DOM), computes the new version when state changes, and updates the real DOM only where needed.
- That way you describe the full UI declaratively, and React figures out the minimal updates for performance.
Real-world idea: describe the UI; React updates only what changed. The virtual DOM enables efficient updates.
Technical definition
- Virtual DOM: lightweight representation of the real DOM in memory. On state change, React builds a new virtual tree and diffs it with the previous one.
- Reconciliation: process of comparing two virtual trees and computing minimal updates to the real DOM. Batch updates for efficiency. Keys help identify list items.
- React does not necessarily update the whole tree — only what changed. Still, avoid unnecessary re-renders (React.memo, useMemo, splitting context).
Simple practical example
Reconciliation: process of comparing two virtual trees and computing minimal updates to the real DOM.
Code example
// Concept: state change → new VDOM tree → diff with previous → patch real DOM (batched)Why it matters
"What is Virtual DOM?" and "How does React update the DOM?" are classic questions. Know diffing and batching.
Interview tip
"Virtual DOM is a lightweight copy of the DOM; React diffs it and patches only changed parts. Keys help list reconciliation. Updates are batched."
React.memo & performance
Simple real-life example (Understand first — very important for understanding)
- Like avoiding unnecessary work: don't re-render the whole tree if only one part changed; don't recompute heavy results if inputs are the same.
- Techniques: memo, useMemo, useCallback, splitting components so only the part that needs new data re-renders, and listing dependencies correctly.
- Measure first (e.g. React DevTools); then optimize where it matters.
Real-world idea: re-render only what needs to. Performance in React is about minimizing work and targeting updates.
Technical definition
React.memo(Component)memoizes the component: re-renders only when props change (shallow compare). Use when parent re-renders often but props are stable.- If you pass inline objects/functions as props, they are new every render so memo has no effect. Pair with useCallback/useMemo for stable references.
- Other tips: lazy load routes (
React.lazy+Suspense), virtualize long lists, avoid inline object/function props in hot paths.
Simple practical example
If you pass inline objects/functions as props, they are new every render so memo has no effect.
Code example
const ExpensiveChild = React.memo(function ExpensiveChild({ data }) {
return <div>{/* heavy render */}</div>;
});Why it matters
"How do you optimize re-renders?" — React.memo for pure components; useCallback/useMemo for stable props. Don't memo everything — measure.
Interview tip
"React.memo avoids re-render when props are same (shallow). Use with useCallback/useMemo so props are stable. Profile before over-optimizing."
Error boundaries
Simple real-life example (Understand first — very important for understanding)
- When a component throws, the whole app doesn't have to crash; an error boundary catches the error in its child tree and can show a fallback UI.
- You define a component that implements getDerivedStateFromError (or use a library) and wrap the part of the tree you want to protect.
- So one broken component shows a message or retry instead of a white screen.
Real-world idea: catch errors in a part of the tree and show a fallback. Error boundaries keep the rest of the app running.
Technical definition
- Error boundaries catch JavaScript errors in child tree and show fallback UI instead of crashing. Implement as class component with
static getDerivedStateFromErrorand/orcomponentDidCatch. - They do not catch errors in event handlers, async code, or SSR. Only in rendering, lifecycle, and constructors of children.
- Wrap critical sections (e.g. a feature route) in an error boundary so one broken component doesn't take down the whole app.
Simple practical example
They do not catch errors in event handlers, async code, or SSR.
Code example
class ErrorBoundary extends React.Component {
state = { hasError: false };
static getDerivedStateFromError() { return { hasError: true }; }
render() {
if (this.state.hasError) return <h1>Something went wrong.</h1>;
return this.props.children;
}
}Why it matters
"How do you handle errors in React?" — error boundary for render errors; try/catch for event handlers and async.
Interview tip
"Error boundary: class component with getDerivedStateFromError/componentDidCatch. Catches render/lifecycle errors; not events or async."
Portals
Simple real-life example (Understand first — very important for understanding)
- Like rendering a component in a different place in the DOM: e.g. a modal that should appear at the top level of the page, not deep inside a sidebar.
- Portals let you keep the component in the React tree (so it can use context and state) but render its output somewhere else in the DOM.
- Use for modals, tooltips, or any UI that should break out of its parent's overflow or z-index.
Real-world idea: render a component's output somewhere else in the page. Portals are for modals and overlays.
Technical definition
ReactDOM.createPortal(child, container)renderschildinto a different DOMcontainer(e.g. a div outside root). Useful for modals, tooltips, dropdowns (escape overflow/z-index).- Event bubbling still works from portal to React tree parent — so click inside modal (in portal) bubbles to the React component that rendered the portal.
- Portal doesn't change the React tree; only the DOM mount point. Useful for accessibility (e.g. render modal into document.body).
Simple practical example
Event bubbling still works from portal to React tree parent — so click inside modal (in portal) bubbles to the React component that rendered the portal.
Code example
return createPortal(
<div className="modal">{content}</div>,
document.body
);Why it matters
"How do you render a modal outside the root div?" — createPortal. Often asked for modals and overlays.
Interview tip
"createPortal(child, domNode) renders into another DOM node. Use for modals so they're not clipped by overflow. Events still bubble to React parent."
Practise the questions
Read the top 50 React interview questions and answers to test yourself after revising.
More Frontend notes
HTML · CSS · JavaScript · JavaScript in the Browser · TypeScript · Angular · All developer notes