1. Components & Props (Very Important)
Components are the building blocks of every React app. Almost every React interview starts here.
1. What is React?
React is a JavaScript library for building user interfaces using reusable components.
Key ideas:
- Component based
- Declarative (you describe what the UI should look like, not how to update it)
- Uses a Virtual DOM for efficient updates
- One-way data flow (parent → child)
Interview Point
React is a library, not a framework. It only handles the view layer. Routing, data fetching and state management come from other packages.
2. JSX
JSX is a syntax extension that lets you write HTML-like markup inside JavaScript.
const element = <h1 className="title">Hello Dipak</h1>;Browsers do not understand JSX. Babel (or SWC) compiles it:
const element = React.createElement("h1", { className: "title" }, "Hello Dipak");JSX Rules
| Rule | Example |
|---|---|
| One root element | wrap in <div> or <>...</> |
class becomes className | <div className="box"> |
for becomes htmlFor | <label htmlFor="name"> |
| Attributes are camelCase | onClick, tabIndex |
Expressions in {} | <p>{user.name}</p> |
| Tags must be closed | <img />, <br /> |
Interview Point
JSX is optional. It is syntactic sugar over React.createElement(). Since React 17, the new JSX transform imports jsx() automatically, so you no longer need import React from "react" just for JSX.
3. React.Fragment
A Fragment lets you return multiple elements without adding an extra DOM node.
function Row() {
return (
<>
<td>Dipak</td>
<td>Developer</td>
</>
);
}Why it matters
An extra wrapper <div> can break CSS grid, flexbox and valid HTML (a <tr> cannot contain a <div>).
When you need the long form
Use <React.Fragment> when you need a key:
{items.map((item) => (
<React.Fragment key={item.id}>
<dt>{item.term}</dt>
<dd>{item.desc}</dd>
</React.Fragment>
))}The short syntax <> does not accept props.
4. Functional vs Class Components
Functional Component
function Welcome({ name }) {
return <h1>Hello {name}</h1>;
}Class Component
class Welcome extends React.Component {
render() {
return <h1>Hello {this.props.name}</h1>;
}
}Comparison
| Feature | Functional | Class |
|---|---|---|
| Syntax | Plain function | ES6 class extending React.Component |
| State | useState hook | this.state + setState |
| Lifecycle | useEffect | componentDidMount etc. |
this keyword | Not used | Required, needs binding |
| Boilerplate | Less | More |
| Modern React | Recommended | Legacy |
| Hooks support | Yes | No |
Interview Point
Since React 16.8, functional components can do everything class components can. Error boundaries are the one exception — they still require a class (or a library like react-error-boundary).
5. Props
Props are read-only inputs passed from a parent to a child.
function Profile({ name, role }) {
return <p>{name} — {role}</p>;
}
<Profile name="Dipak" role="Frontend Dev" />Props Are Immutable
function Bad({ name }) {
name = "Rahul"; // works locally, but never do this
return <p>{name}</p>;
}Never mutate props. Data flows down. To change parent data, the parent passes a callback down.
function Parent() {
const [count, setCount] = useState(0);
return <Child onIncrement={() => setCount(count + 1)} />;
}children Prop
function Card({ children }) {
return <div className="card">{children}</div>;
}
<Card>
<h2>Title</h2>
<p>Body</p>
</Card>Default Props
function Button({ variant = "primary", children }) {
return <button className={variant}>{children}</button>;
}Default parameters replace the old Button.defaultProps, which is deprecated for function components in React 19.
6. State vs Props
| Props | State | |
|---|---|---|
| Owner | Parent | The component itself |
| Mutable | No | Yes (via setter) |
| Purpose | Configure a component | Track changing data |
| Triggers re-render | Yes (when parent re-renders) | Yes |
| Passed down | Yes | Only as props to children |
Interview Point
A one-liner that works: "Props are arguments to a function. State is a variable inside the function that survives between calls."
7. Keys in Lists
Keys help React identify which list items changed, were added or removed.
{users.map((user) => (
<li key={user.id}>{user.name}</li>
))}Why Index as Key Is Bad
{users.map((user, index) => (
<li key={index}>{user.name}</li> // avoid
))}If you delete the first item, every index shifts. React reuses the wrong DOM node, and any internal state (like an <input> value) attaches to the wrong row.
Rules
- Keys must be unique among siblings (not globally)
- Keys must be stable across renders
- Never use
Math.random()as a key — it forces a full remount every render - Index is acceptable only for a static list that never reorders, filters or deletes
Interview Point
Keys are a hint to React's diffing algorithm. Without them React falls back to comparing by position, which causes wrong-state bugs, not just slow renders.
8. Controlled vs Uncontrolled Components
Controlled
React state is the single source of truth.
function Form() {
const [email, setEmail] = useState("");
return (
<input
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
);
}Uncontrolled
The DOM holds the value, and you read it with a ref.
function Form() {
const inputRef = useRef();
const handleSubmit = () => {
console.log(inputRef.current.value);
};
return <input ref={inputRef} defaultValue="" />;
}Comparison
| Controlled | Uncontrolled | |
|---|---|---|
| Source of truth | React state | DOM |
| Value prop | value | defaultValue |
| Re-renders on typing | Yes | No |
| Instant validation | Easy | Hard |
| File input | Not possible | Required |
Interview Point
Controlled is the default recommendation. Use uncontrolled for file inputs, or for large forms where per-keystroke re-renders hurt (this is why react-hook-form is uncontrolled by design).
9. Conditional Rendering
if / else
function Status({ isLoggedIn }) {
if (isLoggedIn) return <Dashboard />;
return <Login />;
}Ternary
<div>{isLoggedIn ? <Dashboard /> : <Login />}</div>Logical AND
<div>{hasError && <p className="error">Something went wrong</p>}</div>The && Trap
{items.length && <List items={items} />}If items.length is 0, React renders the literal 0 on screen. Fix with an explicit boolean:
{items.length > 0 && <List items={items} />}Switching Component Pattern
const PAGES = {
home: Home,
about: About,
contact: Contact,
};
function Page({ name }) {
const Component = PAGES[name] || NotFound;
return <Component />;
}A lookup object beats a long if/else chain and is a common "how would you build a switching component" answer.
10. Higher Order Components (HOC)
A HOC is a function that takes a component and returns a new component. It is a pattern, not a React API.
function withLoading(Component) {
return function WithLoading({ isLoading, ...props }) {
if (isLoading) return <Spinner />;
return <Component {...props} />;
};
}
const UserListWithLoading = withLoading(UserList);Common Real HOCs
React.memoconnect()from React ReduxwithRouter(React Router v5)
Problems with HOCs
- Wrapper hell in DevTools
- Prop name collisions
- Hard to trace where a prop came from
Interview Point
Custom hooks have largely replaced HOCs for logic reuse. HOCs are still useful when you need to wrap or replace the rendered output, not just share logic.
11. Render Props
Sharing logic by passing a function as a prop.
function MouseTracker({ render }) {
const [pos, setPos] = useState({ x: 0, y: 0 });
return (
<div onMouseMove={(e) => setPos({ x: e.clientX, y: e.clientY })}>
{render(pos)}
</div>
);
}
<MouseTracker render={({ x, y }) => <p>{x}, {y}</p>} />Also largely replaced by custom hooks, but still asked in interviews as "name the patterns for code reuse in React": HOC, Render Props, Custom Hooks.
12. Error Boundaries
An error boundary catches JavaScript errors in its child tree, logs them, and shows a fallback UI instead of a blank screen.
class ErrorBoundary extends React.Component {
state = { hasError: false };
static getDerivedStateFromError() {
return { hasError: true };
}
componentDidCatch(error, info) {
console.error(error, info);
}
render() {
if (this.state.hasError) return <h2>Something went wrong.</h2>;
return this.props.children;
}
}What Error Boundaries Do NOT Catch
- Event handler errors (use
try/catch) - Async code (
setTimeout, promises) - Server-side rendering
- Errors thrown inside the boundary itself
Interview Point
Error boundaries must be class components — there is no hook equivalent. In practice most teams use the react-error-boundary package, which wraps the class for you.
13. React Portals
A portal renders a child into a DOM node outside the parent component's DOM hierarchy, while keeping it in the React tree.
import { createPortal } from "react-dom";
function Modal({ children }) {
return createPortal(children, document.getElementById("modal-root"));
}Why
Modals, tooltips and dropdowns break when a parent has overflow: hidden or a z-index stacking context. A portal escapes that.
Interview Point
Events still bubble through the React tree, not the DOM tree. A click inside a portal fires the onClick of its React parent, even though the DOM nodes are far apart.
14. Strict Mode
<React.StrictMode>
<App />
</React.StrictMode>Strict Mode is a development-only tool. It:
- Double-invokes render, state updaters and effects to expose impure code
- Warns about deprecated APIs and legacy string refs
- Since React 18, mounts → unmounts → remounts each component once
Interview Point
"My useEffect runs twice" is almost always Strict Mode in development. It is intentional — it surfaces missing cleanup functions. It does not happen in production builds.
15. Component Lifecycle
The Three Phases
| Phase | Class method | Hook equivalent |
|---|---|---|
| Mounting | constructor, render, componentDidMount | useState init, useEffect(fn, []) |
| Updating | shouldComponentUpdate, render, componentDidUpdate | React.memo, useEffect(fn, [deps]) |
| Unmounting | componentWillUnmount | cleanup returned from useEffect |
| Error | getDerivedStateFromError, componentDidCatch | class only |
Hook Equivalent Of All Three
useEffect(() => {
// componentDidMount + componentDidUpdate
const id = setInterval(tick, 1000);
return () => {
// componentWillUnmount
clearInterval(id);
};
}, [tick]);Interview Point
useEffect is not an exact lifecycle mapping. It is a synchronisation tool: "keep this external system in sync with these values". Interviewers like candidates who say this instead of reciting a method table.
16. Types of Side Effects
| Type | Meaning | Hook |
|---|---|---|
| Cleanup-less | Fire and forget — logging, analytics | useEffect |
| With cleanup | Subscriptions, timers, listeners | useEffect + return function |
| Layout effects | Measuring DOM before paint | useLayoutEffect |
// No cleanup
useEffect(() => {
document.title = `${count} unread`;
}, [count]);
// With cleanup
useEffect(() => {
const onResize = () => setWidth(window.innerWidth);
window.addEventListener("resize", onResize);
return () => window.removeEventListener("resize", onResize);
}, []);Missing the cleanup causes memory leaks and duplicate listeners — a very common interview follow-up.