Frontend Interview Questions (Part 6)
React hooks, useEffect, and side effects management
Frontend Interview Questions (Part 6)
Question 1. What is useEffect
in React?
- A hook for managing side effects (logging, API calls, subscriptions, localStorage, etc.).
- Runs after render, based on dependency array.
Dependency Behavior
useEffect(fn)
→ Runs after every render.useEffect(fn, [])
→ Runs only once (on mount). Cleanup runs on unmount.useEffect(fn, [dep1, dep2])
→ Runs after mount and whenever dependencies change.
Key Notes
- Runs after rendering → cannot block UI paint.
- Dependencies compared by referential equality (e.g.,
ref.current
updates don’t trigger re-runs). - Cleanup: return a function to remove event listeners or cancel timers.
Downsides
- Overuse can cause performance issues (extra re-renders).
- Always executes after render, so updates inside can trigger another render.
Question 2. Essential State vs Derived State
- Essential State → Independent, minimal state (cannot be derived from others).
-
Derived State → Calculated from essential state.
- Example: Cart items = essential state, total price = derived state.
- Best practice: Only store essential state, compute derived values with selectors or
useMemo
.
Question 3. Testing Types Balance (Unit, Integration, E2E)
- Unit Tests → Smallest pieces (functions/components). Fast & reliable.
- Integration Tests → Modules working together (API + UI).
- E2E Tests → Full user flows (signup, login, post).
👉 Good strategy:
- Many unit tests.
- Selective integration tests.
- Critical-path E2E tests.
Question 4. What is Code Coverage?
- % of code executed during tests.
- Frontend: ~60–70% recommended.
- Backend: ~80–90%.
- 100% is rarely useful → diminishing returns, fragile tests.
Question 5. CSR vs SSR vs SSG vs ISR
-
CSR (Client-Side Rendering)
- HTML shell + JS → client builds UI.
- Pros: SPA interactivity. Cons: slow first paint, SEO issues.
-
SSR (Server-Side Rendering)
- Server generates fresh HTML per request.
- Pros: SEO-friendly, fast initial paint. Cons: high server load.
-
SSG (Static Site Generation)
- HTML built at compile-time.
- Pros: fast, cheap, CDN-friendly. Cons: content may be stale.
-
ISR (Incremental Static Regeneration)
- Hybrid: SSG + periodic rebuild.
- Good for blogs, docs, semi-dynamic content.
Question 6. React Hooks Rules
- Must be called at top level of component (not inside loops/conditions).
- Must be called in the same order every render.
Question 7. Is setState
asynchronous?
- Not truly async → it’s batched.
- Multiple updates grouped and applied at once.
-
If you need the latest value immediately, use
useEffect
or updater function:setState((prev) => prev + 1);
Question 8. What is React Scan?
- Tool to visualize unnecessary re-renders.
- Shows why components update (like “Why Did You Render”).
- Functionality now partly integrated into React DevTools.
Question 9. useState
vs Derived State
- React re-renders when
useState
changes. - Derived state = calculated from other state, doesn’t need to be stored.
- If derived computation is expensive → wrap with
useMemo
.
Question 10. Difference: let
variable vs useRef
let
→ reinitialized on every render.useRef
→ persists across renders without triggering re-renders.- Global
let
→ shared across components (may cause unintended side effects).
Question 11. What is a Callback Ref?
-
Instead of
ref={refObj}
, you can pass a function:<input ref={(node) => { ref.current = node; }} />
- Runs when element mounts/unmounts.
- Can perform immediate actions (e.g., focus).
Execution Order
- Callback ref → runs after DOM commit (before
useLayoutEffect
). useLayoutEffect
→ runs synchronously after DOM commit.useEffect
→ runs asynchronously after paint.
👉 Use callback refs to avoid race conditions or when you need early DOM access.
Question 12. What are Render Props?
children
-
Just a prop (ReactNode) automatically passed into components.
const Card = ({ children }) => <div>{children}</div>; <Card> <h1>Hello</h1> </Card>;
Render Props Pattern
-
Passing a function as a prop that returns JSX.
const DataProvider = ({ render }) => { const data = { user: "Hank" }; return render(data); }; <DataProvider render={(d) => <h1>{d.user}</h1>} />;
children as Function
-
children
itself can be a function (function-as-children).const Mouse = ({ children }) => { const [pos, setPos] = useState({ x: 0, y: 0 }); return ( <div onMouseMove={(e) => setPos({ x: e.clientX, y: e.clientY })}> {children(pos)} </div> ); }; <Mouse> {(pos) => ( <p> {pos.x},{pos.y} </p> )} </Mouse>;
👉 Use when you need to pass dynamic data from parent to child rendering logic.