Interview questions

Frontend Interview Questions & Answers

Questions first, then scroll down for answers. Click any question to jump to its answer.

JS JavaScript (Core Depth)

  1. Explain the JavaScript event loop. Microtasks vs macrotasks?
  2. Explain closures with a real-world example.
  3. Explain hoisting in JavaScript.
  4. How does prototypal inheritance work?
  5. Difference between var, let, and const?
  6. Difference between == and ===?
  7. Explain shallow copy vs deep copy. Implement deep clone.
  8. How does `this` behave in arrow functions, class methods, and event handlers?
  9. Explain call, apply, and bind with use cases.
  10. Explain promises, async/await with real examples.
  11. Implement Promise.all from scratch. How is Promise.allSettled different?
  12. Implement debounce and throttle from scratch.
  13. Write polyfills (map, reduce, bind).
  14. Is JavaScript tightly coupled or loosely coupled?
  15. Difference between fetch and axios?
  16. Write code to find frequency of elements in an array.
  17. Difference between microtask and macrotask queue with a real example.
  18. Event Delegation & Bubbling.

TS TypeScript

  1. Why do we use TypeScript?
  2. How does "extends" work in TypeScript? Difference between type and interface?

React React (Core Concepts)

  1. What is React and why is it efficient?
  2. How does React work internally?
  3. Explain React Fiber.
  4. What is reconciliation? How does React diffing work?
  5. Why are keys important in lists?
  6. Explain React rendering lifecycle.
  7. Difference between state and props in React.
  8. Controlled vs uncontrolled components.
  9. What causes unnecessary re-renders? How do you avoid them?
  10. Explain useEffect deeply. Cleanup? Dependency array pitfalls?
  11. Difference between useMemo and useCallback. When would you use React.memo?
  12. What is state batching? What changed in React 18?
  13. How does React Context work? When can it hurt performance?
  14. Build a custom hook like useDebounce or useFetch.
  15. How does Redux work, from installation to usage?
  16. Redux Toolkit vs Redux? TanStack Query?
  17. What are stale closures in React?
  18. What causes memory leaks in React apps?
  19. Component Lifecycle.
  20. What are Error Boundaries? Explain implementation.
  21. How do you handle errors in React applications?
  22. What is state scheduling?
  23. How to send data from parent to child? What is prop drilling?

React React Coding Questions

  1. Build a debounced search input.
  2. Implement infinite scroll (Intersection Observer API).
  3. Create a custom useFetch hook with loading, error, and data.
  4. Prevent unnecessary re-renders using React.memo, useMemo, useCallback.
  5. Build form with controlled inputs + validation.
  6. Implement Dark/Light Mode using Context API.
  7. Role-Based Routing with JWT + React Router.
  8. Shopping Cart Logic (add/remove/update quantity + total).
  9. File Upload with Preview.
  10. Build a Modal from Scratch (reusable, ESC key, backdrop).
  11. Create a reusable dropdown with search and multi-select.
  12. Build a product listing page with search, filters, and cart.
  13. Design a reusable toast notification system.

Perf Performance & Optimization

  1. How do you optimize performance of a React application?
  2. What is lazy loading?
  3. What is code splitting?
  4. What is tree shaking?
  5. Explain repaint vs reflow vs compositing.
  6. How does browser rendering work internally?
  7. How do you optimize bundle size in React?
  8. How would you improve Web Vitals (LCP, CLS, INP)?
  9. Explain browser caching strategies.
  10. How do you debug frontend performance bottlenecks?
  11. What causes UI jank?
  12. How to optimize React rendering for large lists (10k+ rows)?
  13. What is WebSocket?
  14. What is Service Worker?

Design Frontend System Design

  1. Design an autocomplete search with debouncing and caching.
  2. Design an infinite scrolling feed.
  3. How would you design a scalable dashboard with 100+ pages?
  4. Design a reusable component library for a large team.
  5. Redux vs Context vs Zustand — how do you decide?
  6. SSR vs SSG vs ISR — when would you use each?
  7. How to architect a scalable frontend for 1M+ users daily?
  8. How to optimize an eCommerce product listing page?
  9. Design a Real-time Dashboard (with failure handling).
  10. Handle API caching on client.

Web Web Concepts & Browser

  1. Difference between CSR, SSR, SSG, ISR, and hydration?
  2. Explain hydration mismatch.
  3. What happens when a user types a URL in the browser?
  4. Difference between localStorage and sessionStorage?
  5. Explain optimistic UI updates.
  6. Explain race conditions in frontend applications.
  7. How do you cancel ongoing API requests in React?
  8. How do you handle API retries and failures?
  9. How do you handle API rate limits on the frontend?
  10. How do you monitor frontend applications in production?
  11. Explain accessibility best practices.
  12. REST APIs & HTTP Methods.
  13. Explain CORS in simple terms.
  14. Difference between synchronous and asynchronous JavaScript?

Sec Security & Authentication

  1. How do you prevent XSS, CSRF, and token leakage?
  2. How do you securely store tokens in frontend apps?
  3. Explain authentication vs authorization.
  4. Explain JWT authentication end-to-end with refresh flow.
  5. How do refresh tokens work internally?
  6. Frontend security vulnerabilities developers should know.

Node Backend (Node.js / Database)

  1. How do you design scalable REST APIs in Node.js?
  2. Explain authentication using JWT and refresh tokens (backend).
  3. How to handle caching and performance optimization in backend?
  4. SQL vs NoSQL — when to choose MongoDB over MySQL?
  5. Explain indexing and query optimization techniques.
  6. Design a scalable e-commerce or chat application architecture.

DSA Data Structures & Algorithms

  1. Find the second largest element in an array (O(n)).
  2. Maximum sum subarray (Kadane's algorithm).
  3. Sliding window maximum.
  4. Merge k sorted linked lists.
  5. Detect a cycle in a linked list.
  6. Longest palindromic substring.
  7. Design and implement an LRU Cache.
  8. Remove duplicate objects from an array based on a key.

Debug Scenario-Based / Debugging

  1. Duplicate API Calls Issue in SPA.
  2. Works in Staging, Fails in Production.
  3. Bundle is Slow After Deployment.
  4. React Re-renders — too many unnecessary re-renders.
  5. System Design + Failure Handling (Real-time Dashboard).

HR Behavioral / Managerial

  1. Tell me about a challenging production issue you resolved.
  2. How do you handle code reviews and mentor junior developers?
  3. How do you manage conflicting priorities?
  4. What's your approach when requirements change during sprint?
  5. How do you handle disagreements in technical decisions?
  6. How do you balance performance vs feature delivery?
  7. How do you prioritize technical debt vs new features?
  8. How do you explain technical decisions to non-technical stakeholders?
  9. What is the most challenging task you handled in your project?
  10. Explain a frontend project you built end-to-end.
  11. Why migrate from Angular to React? Challenges?
  12. How do you handle conflicts with designers or backend teams?

Next Next.js

  1. What is Next.js and how does it differ from plain React?
  2. Explain SSR, SSG, ISR, and CSR — when would you choose each?
  3. App Router vs Pages Router — key differences?
  4. What are React Server Components? How do they work in Next.js?
  5. Difference between Server Component and Client Component?
  6. How does data fetching work in the App Router?
  7. What is Incremental Static Regeneration (ISR)? How does revalidation work?
  8. How does caching work in Next.js 13+? (fetch cache, revalidateTag)
  9. What are Server Actions in Next.js?
  10. How does Next.js routing work? (dynamic routes, catch-all, parallel routes)
  11. How do you handle authentication in Next.js using Middleware?
  12. How does Next.js optimize images and fonts?
  13. What is Next.js Middleware and what can you use it for?
  14. How do you manage environment variables in Next.js?
  15. How do you optimize performance in a Next.js application?

Nest NestJS

  1. What is NestJS and how does it differ from Express?
  2. Explain the Module, Controller, and Provider pattern in NestJS.
  3. How does Dependency Injection work in NestJS?
  4. What are Guards, Pipes, Interceptors, and Middleware? What is their execution order?
  5. How do you implement JWT authentication in NestJS?
  6. How do you implement RBAC (Role-Based Access Control) in NestJS?
  7. What are DTOs and how does validation work with class-validator?
  8. How do decorators work in NestJS? Build a custom decorator.
  9. How do you integrate TypeORM or Prisma with NestJS?
  10. How do you implement microservices communication in NestJS?
  11. What is the difference between DEFAULT, REQUEST, and TRANSIENT provider scopes?
  12. How do you implement caching in NestJS?
  13. How do you test a NestJS application? (unit + e2e)
  14. How do you handle exceptions in NestJS? (Exception Filters)
  15. What is CQRS pattern in NestJS and when would you use it?

Interview Process References

CompanyPackageRounds
EY (Sr Software Developer, 4+ yrs)28 LPAR1: React/JS/DSA → R2: Node/System Design/DB → R3: Behavioral
MeeshoR1: OA (HackerEarth) → R2: JS Phone Screen → R3: Machine Coding → R4: LLD → R5: Hiring Manager

Answers

Click any question above to jump here, or scroll through all answers below.

JS JavaScript — Answers

1. Event Loop, Microtasks vs Macrotasks

JS runs one thing at a time (single-threaded). The event loop checks: "Is the call stack empty? If yes, pick the next task from the queue."

Microtasks (Promises) always run BEFORE macrotasks (setTimeout).

console.log("1");
setTimeout(() => console.log("2"), 0);    // macrotask
Promise.resolve().then(() => console.log("3"));  // microtask
console.log("4");

// Output: 1, 4, 3, 2
// Why? Sync code first (1, 4) → microtask (3) → macrotask (2)
Back to questions

2. Closures

A function that remembers variables from where it was created, even after that outer function is done.

function counter() {
  let count = 0;
  return function() { return ++count; };
}
const inc = counter();
inc(); // 1
inc(); // 2  (it remembers count!)

Used for: keeping data private, factory functions, event handlers.

Back to questions

3. Hoisting

JS moves declarations to the top before running code.

  • var → moved up, starts as undefined
  • let/const → moved up but CAN'T use before their line (Temporal Dead Zone → error)
  • function declarations → fully moved up, can call before their line
  • Arrow functions → NOT hoisted
Back to questions

4. Prototypal Inheritance

Every object has a parent object (prototype). If a property isn't found on the object, JS looks at its parent, then grandparent, and so on.

const animal = { speak() { return "hello"; } };
const dog = Object.create(animal);
dog.speak(); // works! Found it on parent (animal)
Back to questions

5. var vs let vs const

Featurevarletconst
ScopeFunctionBlock { }Block { }
Re-declareYesNoNo
Re-assignYesYesNo
HoistingundefinedTDZ (error)TDZ (error)

Note: const objects can still have properties changed: const obj = {}; obj.name = "John"; // works!

Back to questions

6. == vs ===

  • == (loose): converts types then compares. "5" == 5 → true
  • === (strict): does NOT convert types. "5" === 5 → false

Always use === to avoid surprises.

Back to questions

7. Shallow Copy vs Deep Copy

  • Shallow copy: copies first level only. Nested objects still point to original.
  • Deep copy: copies everything including nested objects.
// Shallow copy
const copy = { ...original };

// Deep copy (modern)
const copy = structuredClone(original);

// Deep copy (older)
const copy = JSON.parse(JSON.stringify(original));

// Manual deep clone
function deepClone(obj) {
  if (obj === null || typeof obj !== 'object') return obj;
  const clone = Array.isArray(obj) ? [] : {};
  for (let key in obj) {
    if (obj.hasOwnProperty(key)) clone[key] = deepClone(obj[key]);
  }
  return clone;
}
Back to questions

8. `this` Behavior

Contextthis points to
Object methodThe object itself
Regular functionwindow (browser) / undefined (strict)
Arrow functionTakes `this` from parent scope
Event handlerThe element clicked
Class methodThe instance

Lost `this`? Use .bind(this) or arrow function to fix.

Back to questions

9. call, apply, bind

All three let you set what `this` should be.

function greet(msg) { return `${msg}, ${this.name}`; }

// call → runs NOW, args one by one
greet.call({ name: "John" }, "Hi");     // "Hi, John"

// apply → runs NOW, args as array
greet.apply({ name: "John" }, ["Hi"]);  // "Hi, John"

// bind → returns NEW function for later
const bound = greet.bind({ name: "John" });
bound("Hi");  // "Hi, John"
Back to questions

10. Promises & async/await

Promise = "I'll give you the result later" (pending → success or fail).

async/await = cleaner way to write promises.

// Promise way
fetch(url).then(res => res.json()).then(data => console.log(data)).catch(err => console.error(err));

// async/await way (same thing, cleaner)
async function getData() {
  try {
    const res = await fetch(url);
    const data = await res.json();
    console.log(data);
  } catch (err) { console.error(err); }
}
Back to questions

11. Implement Promise.all

Runs multiple promises together, returns all results. Fails if ANY one fails.

function promiseAll(promises) {
  return new Promise((resolve, reject) => {
    const results = [];
    let done = 0;
    if (promises.length === 0) return resolve([]);
    promises.forEach((p, i) => {
      Promise.resolve(p)
        .then(val => {
          results[i] = val;
          if (++done === promises.length) resolve(results);
        })
        .catch(reject);
    });
  });
}

Promise.allSettled: waits for ALL, never fails early. Use when you want all results even if some fail.

Back to questions

12. Debounce & Throttle

Debounce: wait until user STOPS, then run. Throttle: run at most once every X ms.

// Debounce (e.g., search after typing stops)
function debounce(fn, delay) {
  let timer;
  return (...args) => {
    clearTimeout(timer);
    timer = setTimeout(() => fn(...args), delay);
  };
}

// Throttle (e.g., scroll handler fires max once per 200ms)
function throttle(fn, limit) {
  let lastCall = 0;
  return (...args) => {
    if (Date.now() - lastCall >= limit) {
      lastCall = Date.now();
      fn(...args);
    }
  };
}
Back to questions

13. Polyfills (map, reduce, bind)

// map: transform each item, return new array
Array.prototype.myMap = function(cb) {
  const result = [];
  for (let i = 0; i < this.length; i++) result.push(cb(this[i], i, this));
  return result;
};

// reduce: combine all items into single value
Array.prototype.myReduce = function(cb, init) {
  let acc = init !== undefined ? init : this[0];
  for (let i = init !== undefined ? 0 : 1; i < this.length; i++) acc = cb(acc, this[i], i, this);
  return acc;
};

// bind: create new function with fixed `this`
Function.prototype.myBind = function(ctx, ...args) {
  const fn = this;
  return (...newArgs) => fn.apply(ctx, [...args, ...newArgs]);
};
Back to questions

14. JS Coupling

Loosely coupled — parts of code can work independently. We achieve this using modules (import/export), events, callbacks. Tightly coupled = changing one part breaks another.

Back to questions

15. fetch vs axios

Featurefetchaxios
Built-in?Yes (browser native)No (install separately)
JSON parsingNeed .json()Auto-parses
Error on 404/500Does NOT throwDOES throw
InterceptorsNoYes
Cancel requestAbortControllerBuilt-in cancel
Back to questions

16. Frequency of Elements

function frequency(arr) {
  return arr.reduce((acc, val) => {
    acc[val] = (acc[val] || 0) + 1;
    return acc;
  }, {});
}
frequency([1,2,2,3,3,3]); // { 1:1, 2:2, 3:3 }
Back to questions

17. Microtask vs Macrotask

  • Microtask (high priority): Promise.then — runs right after current code finishes.
  • Macrotask (lower priority): setTimeout — runs in next round.
  • ALL microtasks finish BEFORE any macrotask runs.
Back to questions

18. Event Delegation & Bubbling

Bubbling: click on child → event goes UP to parent → grandparent → ...

Event Delegation: add ONE click on parent, check which child was clicked.

ul.addEventListener("click", (e) => {
  if (e.target.tagName === "LI") console.log(e.target.textContent);
});

Why? Fewer listeners, works for dynamically added items.

Back to questions

TS TypeScript — Answers

1. Why TypeScript

  • Catches errors BEFORE running the code (compile time).
  • Better autocomplete in VS Code.
  • Code is self-documenting (you see types).
  • Easier teamwork on large projects.
Back to questions

2. extends & type vs interface

// extends: one interface builds on top of another
interface Animal { name: string; }
interface Dog extends Animal { breed: string; }
// Dog has both name + breed

// interface: for object shapes, auto-merges
interface User { name: string; }
interface User { age: number; }  // merged!

// type: more flexible — unions, tuples, etc.
type ID = string | number;  // can't do with interface

Simple rule: Use interface for objects, type for everything else.

Back to questions

React React Core — Answers

1. What is React

A JS library to build UI using reusable components. Fast because of Virtual DOM — only updates what actually changed on screen.

Back to questions

2. How React Works Internally

You write JSX
    ↓
React converts to JS objects (Virtual DOM)
    ↓
When state changes → new Virtual DOM created
    ↓
React COMPARES old vs new (diffing)
    ↓
Only the CHANGED parts get updated on real screen
Back to questions

3. React Fiber

React's internal engine (since React 16). Breaks big rendering into small pieces so browser doesn't freeze. Can pause, prioritize, and resume work.

Example: user typing (high priority) won't be blocked by data loading (low priority).

Back to questions

4. Reconciliation & Diffing

  • React compares old and new Virtual DOM trees.
  • Different element type? → Rebuild everything below.
  • Same type? → Update changed attributes only.
  • Lists? → Uses "key" to track items.
Back to questions

5. Why Keys Matter

Keys tell React which item is which in a list. Without keys → mix-ups and unnecessary re-renders. Use unique IDs, NOT array index (breaks when list order changes).

Back to questions

6. React Lifecycle

Mount (born)     → component appears → useEffect(() => {}, []) runs
Update (changed) → state/props change → re-render → useEffect runs again
Unmount (dies)   → component removed → useEffect cleanup runs
Back to questions

7. State vs Props

FeaturePropsState
SourceFrom parentInside component
Mutable?Read-onlyCan change (useState)
DirectionFlows downLocal only
Back to questions

8. Controlled vs Uncontrolled

// Controlled: React controls the value
<input value={name} onChange={e => setName(e.target.value)} />

// Uncontrolled: DOM controls the value, read with ref
<input ref={myRef} />  →  myRef.current.value

Controlled = more control (validation). Uncontrolled = simpler.

Back to questions

9. Unnecessary Re-renders

Causes: parent re-renders → child re-renders too, new object/function refs created every render.

Fix: React.memo (skip re-render if props same), useMemo (cache values), useCallback (cache functions).

Back to questions

10. useEffect

useEffect(() => {
  // runs AFTER render
  return () => { /* cleanup */ };
}, [deps]);

// []     → run once (mount)
// [x]    → run when x changes
// nothing → every render

Mistakes: forgetting deps (stale data), object deps (new ref → infinite loop).

Back to questions

11. useMemo vs useCallback vs React.memo

useMemo     → caches a VALUE:    const total = useMemo(() => calc(items), [items])
useCallback → caches a FUNCTION: const handleClick = useCallback(() => {...}, [deps])
React.memo  → wraps a COMPONENT to skip re-render if props unchanged
Back to questions

12. State Batching

React groups multiple setState calls into ONE re-render (for performance).

  • React 17: batched only inside click handlers.
  • React 18: batches EVERYWHERE — setTimeout, promises, etc.
Back to questions

13. Context API

Share data across components without prop drilling: Create → Provide → Consume (useContext).

Problem: ALL consumers re-render when value changes. Fix: split into multiple contexts or use Zustand/Redux for frequent updates.

Back to questions

14. Custom Hooks

// useDebounce — delays value updates
function useDebounce(value, delay) {
  const [debounced, setDebounced] = useState(value);
  useEffect(() => {
    const timer = setTimeout(() => setDebounced(value), delay);
    return () => clearTimeout(timer);
  }, [value, delay]);
  return debounced;
}

// useFetch — fetches data from URL
function useFetch(url) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);
  useEffect(() => {
    fetch(url).then(r => r.json()).then(setData).catch(setError).finally(() => setLoading(false));
  }, [url]);
  return { data, loading, error };
}
Back to questions

15. Redux

One big STORE holds all app state
         ↓
Component DISPATCHES an ACTION   →   dispatch({ type: "ADD_ITEM", payload: item })
         ↓
REDUCER returns NEW state        →   (state, action) => newState
         ↓
Component RE-RENDERS with new data
Back to questions

16. RTK vs Redux vs TanStack Query

  • RTK: simpler, less code, uses createSlice (auto-creates actions + reducer).
  • Old Redux: more boilerplate (action types, switch cases).
  • TanStack Query: for server state (fetching/caching API data) — different from client state management.
Back to questions

17. Stale Closures

A function remembers OLD state value instead of the current one. Common in useEffect with empty deps — setTimeout captures initial state.

Fix: add correct dependencies, or use setState(prev => prev + 1) (functional update).

Back to questions

18. Memory Leaks

Caused by: timers not cleared, event listeners not removed, fetch requests not cancelled after component unmounts.

Fix: always return cleanup in useEffect.

useEffect(() => {
  const timer = setInterval(fetchData, 5000);
  return () => clearInterval(timer);  // cleanup!
}, []);
Back to questions

19. Component Lifecycle

Mount → Render → useEffect → Update → Re-render → useEffect cleanup + re-run → Unmount → Final cleanup.

Back to questions

20. Error Boundaries

Catches errors in children — like try-catch for UI. Shows fallback UI instead of crashing the whole app. Must be a class component with getDerivedStateFromError.

Does NOT catch: event handler errors, async errors (use try-catch for those).

Back to questions

21. Error Handling

UI errors → Error Boundaries. Async/event errors → try-catch. Log errors to services like Sentry or LogRocket. Show friendly error states to users.

Back to questions

22. State Scheduling

React doesn't apply state updates instantly — it schedules them. startTransition marks an update as "not urgent, do it when free" — keeps typing and interactions smooth while heavy updates happen in the background.

Back to questions

23. Props & Prop Drilling

Pass data from parent to child using props. Prop drilling = passing props through many middle components that don't need them.

Fix: Context API, Redux, Zustand, or component composition.

Back to questions

React React Coding — Answers

1. Debounced Search

const [query, setQuery] = useState("");
const debounced = useDebounce(query, 500);

useEffect(() => { if (debounced) searchAPI(debounced); }, [debounced]);

return <input value={query} onChange={e => setQuery(e.target.value)} />;
Back to questions

2. Infinite Scroll

const loaderRef = useRef();
useEffect(() => {
  const observer = new IntersectionObserver(entries => {
    if (entries[0].isIntersecting) loadMore();
  });
  observer.observe(loaderRef.current);
  return () => observer.disconnect();
}, []);

// At bottom of list: <div ref={loaderRef}>Loading...</div>
Back to questions

3. useFetch Hook

See React Core Q14 above for full code. Returns { data, loading, error }.

Back to questions

4. Prevent Re-renders

const Child = React.memo(({ onClick }) => <button onClick={onClick}>Click</button>);

function Parent() {
  const handleClick = useCallback(() => doSomething(), []);
  const data = useMemo(() => expensiveCalc(input), [input]);
  return <Child onClick={handleClick} />;
}
Back to questions

5. Form Validation

const [email, setEmail] = useState("");
const [error, setError] = useState("");
const submit = () => {
  if (!/\S+@\S+\.\S+/.test(email)) setError("Invalid email");
  else { setError(""); sendData(email); }
};
Back to questions

6. Dark/Light Mode

const ThemeCtx = createContext();
function ThemeProvider({ children }) {
  const [theme, setTheme] = useState("light");
  const toggle = () => setTheme(t => t === "light" ? "dark" : "light");
  return <ThemeCtx.Provider value={{ theme, toggle }}>{children}</ThemeCtx.Provider>;
}
// Use: const { theme, toggle } = useContext(ThemeCtx);
// Apply: <div className={theme}>
Back to questions

7. Protected Route

function ProtectedRoute({ children, role }) {
  const user = getUser();  // decode JWT from cookie/storage
  if (!user) return <Navigate to="/login" />;
  if (user.role !== role) return <Navigate to="/403" />;
  return children;
}
Back to questions

8. Cart Logic

Add:        setCart([...cart, { ...product, qty: 1 }])
Remove:     setCart(cart.filter(i => i.id !== id))
Update qty: setCart(cart.map(i => i.id === id ? {...i, qty} : i))
Total:      cart.reduce((sum, i) => sum + i.price * i.qty, 0)
Back to questions

9. File Upload Preview

const [preview, setPreview] = useState(null);
const handleFile = (e) => setPreview(URL.createObjectURL(e.target.files[0]));
// <input type="file" onChange={handleFile} />
// {preview && <img src={preview} alt="preview" />}
Back to questions

10. Modal from Scratch

function Modal({ isOpen, onClose, children }) {
  useEffect(() => {
    const esc = (e) => { if (e.key === "Escape") onClose(); };
    if (isOpen) document.addEventListener("keydown", esc);
    return () => document.removeEventListener("keydown", esc);
  }, [isOpen]);
  if (!isOpen) return null;
  return createPortal(
    <div className="backdrop" onClick={onClose}>
      <div className="modal" onClick={e => e.stopPropagation()}>{children}</div>
    </div>, document.getElementById("modal-root")
  );
}
Back to questions

11. Multi-Select Dropdown

Filter options by search text, toggle selection with checkboxes, show selected count in the trigger button.

const [selected, setSelected] = useState([]);
const [search, setSearch] = useState("");
const filtered = options.filter(o => o.label.toLowerCase().includes(search.toLowerCase()));
const toggle = (val) => setSelected(s => s.includes(val) ? s.filter(x => x !== val) : [...s, val]);
Back to questions

12. Product Listing Page

  • State: useReducer for filters + cart, URL params (useSearchParams) to reflect active filters.
  • Cart persistence: useEffect to sync cart to localStorage on change.
  • Memoization: React.memo on product cards, useMemo for filtered product list.
  • Skeleton loaders: show placeholder cards while fetching, replace with real data on load.
Back to questions

13. Toast Notification System

  • State: array of toasts in Context, each with id, message, type, duration.
  • Auto-dismiss: useEffect per toast with setTimeout → remove by id.
  • Accessibility: aria-live="polite" on container so screen readers announce new toasts.
  • Framework-agnostic: expose a vanilla JS API (toast.show()) that dispatches a custom DOM event.
Back to questions

Perf Performance — Answers

1. Optimize React App

  • Code splitting & lazy loading (React.lazy + Suspense)
  • React.memo, useMemo, useCallback to prevent re-renders
  • Virtualize long lists (react-window / react-virtual)
  • Debounce/throttle expensive operations
  • Optimize images (WebP, lazy load, proper sizing)
  • Reduce bundle size, enable gzip/brotli compression
Back to questions

2. Lazy Loading

Load things only when needed — saves bandwidth and speeds up initial load.

  • Images: <img loading="lazy" />
  • Components: const Page = React.lazy(() => import('./Page'))
Back to questions

3. Code Splitting

Break app into smaller JS files. Load each page's code only when user visits it. Uses dynamic import() — bundler creates separate chunks automatically.

Back to questions

4. Tree Shaking

Bundler removes unused code automatically. Requires ES modules (import/export), not CommonJS (require). Example: importing only { format } from date-fns instead of the whole library.

Back to questions

5. Repaint vs Reflow vs Compositing

TypeTriggered byCost
Reflow (Layout)Size/position changesMost expensive
RepaintColor/background changesMedium
Compositingtransform/opacity (GPU)Cheapest

Use transform and opacity for animations — they skip layout and paint entirely.

Back to questions

6. Browser Rendering

HTML → DOM Tree
CSS  → CSSOM Tree
           ↓
     Render Tree (visible nodes only)
           ↓
     Layout (calculate positions/sizes)
           ↓
     Paint (fill pixels)
           ↓
     Composite (GPU layers → screen)
Back to questions

7. Optimize Bundle Size

  • Analyze with webpack-bundle-analyzer or vite's rollup-plugin-visualizer
  • Replace heavy libs: moment.js → dayjs, lodash → individual imports
  • Enable gzip/brotli in server config
  • Code-split routes, lazy-load heavy components
  • Use CDN for large static assets
Back to questions

8. Web Vitals (LCP, CLS, INP)

  • LCP (Largest Contentful Paint — loading speed): optimize hero images, preload fonts, use SSR, CDN.
  • CLS (Cumulative Layout Shift — visual stability): set explicit sizes on images/videos, don't inject content above existing content.
  • INP (Interaction to Next Paint — responsiveness): don't block main thread, debounce inputs, use Web Workers for heavy tasks.
Back to questions

9. Browser Caching

  • Cache-Control headers: max-age=31536000 for hashed static assets (CSS/JS), no-cache for HTML.
  • ETags: server sends a fingerprint — browser sends it back, server replies 304 Not Modified if unchanged.
  • Service Worker: cache assets offline, serve from cache-first or network-first strategy.
Back to questions

10. Debug Performance

  • Chrome DevTools Performance tab: record interactions, see long tasks and bottlenecks.
  • Lighthouse: automated audit for Web Vitals, accessibility, best practices.
  • React Profiler: find which components re-render and how long they take.
  • web-vitals library: measure LCP/CLS/INP in real user sessions.
Back to questions

11. UI Jank

Screen freezes when the main thread is busy for more than 16ms (1 frame at 60fps).

Fix: move heavy work to Web Workers, use GPU animations (transform/opacity), debounce scroll/resize handlers, virtualize long lists.

Back to questions

12. Large Lists (10k+ rows)

Use virtualization — only render the rows currently visible in the viewport, not all 10,000.

Libraries: react-window (lightweight) or @tanstack/react-virtual (more flexible).

Back to questions

13. WebSocket

A persistent two-way connection between browser and server. Unlike HTTP (request-response), server can push data at any time.

Use cases: chat apps, live dashboards, stock tickers, multiplayer games.

const ws = new WebSocket("wss://example.com/ws");
ws.onmessage = (e) => console.log(e.data);
ws.send("hello server");
Back to questions

14. Service Worker

A background script that runs separately from the page. Acts as a proxy between browser and network.

  • Offline caching: intercept fetch requests, serve from cache when offline.
  • Push notifications: receive messages even when app is closed.
  • Background sync: queue actions when offline, replay when back online.
Back to questions

Design System Design — Answers

1. Autocomplete Search

Debounce input (300ms) → cancel previous request (AbortController) → call API → cache results in a Map → show dropdown → support keyboard navigation (ArrowUp/Down/Enter).

Back to questions

2. Infinite Feed

IntersectionObserver at bottom sentinel → load next page (cursor-based pagination) → append items → virtualize with react-window for performance → show skeleton loaders while fetching.

Back to questions

3. Scalable Dashboard (100+ pages)

  • Lazy-load each page with React.lazy + Suspense
  • Feature-based folder structure (not file-type-based)
  • Shared layout with nested routing (React Router v6)
  • Micro-frontends for large teams (Module Federation)
  • Prefetch next likely pages on hover
Back to questions

4. Reusable Component Library

  • Design tokens: colors, spacing, typography as CSS variables
  • Storybook: live docs + visual testing for every component
  • npm package: publish with proper tree-shaking exports
  • Accessibility: ARIA roles, keyboard navigation baked in
  • TypeScript: typed props for autocomplete and safety
Back to questions

5. Redux vs Context vs Zustand

ContextRedux (RTK)Zustand
Best forTheme, auth (low freq)Complex apps, devtoolsMedium apps, simple API
BoilerplateNoneModerateMinimal
Frequent updatesBad (all re-render)GoodGood
Back to questions

6. SSR vs SSG vs ISR

  • SSR: server renders on every request. Good for dynamic/personalized content and SEO.
  • SSG: pages built once at deploy time. Fastest possible — great for blogs, docs.
  • ISR: SSG + pages auto-regenerate in background after a set time. Best of both worlds.
Back to questions

7. Scalable Frontend for 1M+ Users

CDN for static assets → code split + lazy load → service workers for offline → performance monitoring → edge caching (Cloudflare) → micro-frontends for team scalability.

Back to questions

8. eCommerce Product Listing

SSR for first page (SEO) → lazy-load images (next/image) → virtualized grid for large catalogs → skeleton loaders → debounced search → TanStack Query for client-side caching.

Back to questions

9. Real-time Dashboard

WebSocket for live data → auto-reconnect with exponential backoff → buffer/queue updates to avoid UI flooding → Web Workers for heavy data processing → show stale cached data while reconnecting.

Back to questions

10. Client-side API Caching

  • TanStack Query / SWR: auto-caching, stale-while-revalidate, background refetch, deduplication of requests.
  • Manual: const cache = new Map() with TTL check before fetching.
Back to questions

Web Web Concepts — Answers

1. CSR vs SSR vs SSG vs ISR

CSR  → Browser renders everything (slow first load, fast navigation)
SSR  → Server sends ready HTML (fast first load, good SEO)
SSG  → HTML built at deploy time (fastest, good for static content)
ISR  → SSG + pages auto-refresh in background after TTL
Hydration → Making server HTML interactive by attaching JS event listeners
Back to questions

2. Hydration Mismatch

Server HTML ≠ client HTML. React throws a warning and re-renders from scratch.

Causes: using window, Date.now(), localStorage, or random values during render.

Fix: move client-only code into useEffect.

Back to questions

3. What Happens When You Type a URL

1. DNS lookup → resolve domain to IP address
2. TCP + TLS handshake → establish secure connection
3. HTTP request sent → GET /path HTTP/1.1
4. Server responds → HTML, status 200
5. Browser parses HTML → builds DOM
6. Fetches CSS → builds CSSOM → Render Tree
7. Fetches JS → executes scripts
8. Layout → Paint → Composite → Screen
Back to questions

4. localStorage vs sessionStorage

localStoragesessionStorage
LifetimeForever (manual clear)Until tab closes
ScopeAll tabs (same origin)Per tab only
Size~5MB~5MB
Back to questions

5. Optimistic UI

Update the UI instantly before the server responds. If server fails, roll back. Makes the app feel faster.

Example: hitting Like instantly turns the icon red, then if the API call fails you flip it back and show an error.

Back to questions

6. Race Conditions

Two API calls finish in the wrong order — the older response overwrites the newer one.

Fix: use AbortController to cancel the previous request when a new one starts.

Back to questions

7. Cancel API Requests

useEffect(() => {
  const controller = new AbortController();
  fetch(url, { signal: controller.signal })
    .then(r => r.json()).then(setData)
    .catch(e => { if (e.name !== "AbortError") setError(e); });
  return () => controller.abort();  // cancel on cleanup
}, [url]);
Back to questions

8. API Retries & Failures

Retry with exponential backoff (1s, 2s, 4s...), max 3–5 attempts. Only retry on network errors or 5xx, not 4xx. Show spinner during retry, show error state if all fail.

Back to questions

9. API Rate Limits (HTTP 429)

When server returns 429 Too Many Requests: queue further requests, respect the Retry-After header, increase client-side caching to reduce call frequency, debounce user-triggered actions.

Back to questions

10. Monitor Frontend

  • Sentry: capture JS errors with stack traces and user context.
  • web-vitals: measure LCP/CLS/INP from real users.
  • Google Analytics / Datadog RUM: user flows and performance.
Back to questions

11. Accessibility

  • Use semantic HTML (<button> not <div onClick>, <nav>, <main>)
  • Alt text on images, labels on form inputs
  • Full keyboard navigation (Tab, Enter, Escape, Arrow keys)
  • Color contrast ratio ≥ 4.5:1 for text
  • ARIA roles/labels where HTML semantics are insufficient
Back to questions

12. REST & HTTP Methods

MethodActionIdempotent?
GETReadYes
POSTCreateNo
PUTReplaceYes
PATCHPartial updateNo
DELETERemoveYes
Back to questions

13. CORS

Browser blocks requests to a different origin (domain/port/protocol) for security. Server must explicitly allow it.

// Server response header:
Access-Control-Allow-Origin: https://yourapp.com
Access-Control-Allow-Methods: GET, POST, PUT
Back to questions

14. Sync vs Async

Synchronous: one task blocks until it finishes — next line can't run. Asynchronous: start a task and move on — handle result later via callback/promise/await.

Back to questions

Sec Security — Answers

1. XSS & CSRF Prevention

  • XSS: never use innerHTML with user input. React escapes JSX by default. Sanitize with DOMPurify if you must render HTML. Add Content-Security-Policy headers.
  • CSRF: use CSRF tokens in forms, set cookies with SameSite=Strict or SameSite=Lax.
Back to questions

2. Store Tokens Safely

Best: httpOnly cookies (JS cannot access them — safe from XSS). Set Secure + SameSite flags.

NEVER: localStorage or sessionStorage — any XSS attack can steal tokens stored there.

Back to questions

3. Authentication vs Authorization

Authentication: proving WHO you are — login with email/password, OAuth, biometrics.

Authorization: checking WHAT you're allowed to do — role-based access, permissions.

Back to questions

4. JWT Flow with Refresh Tokens

Login → server returns:
  - Access token (short-lived: 15min) — stored in memory
  - Refresh token (long-lived: 7 days) — stored in httpOnly cookie
         ↓
Every API call → send access token in Authorization header
         ↓
Access token expired → automatically send refresh token → get new access token
         ↓
Refresh token expired → redirect to login
         ↓
Logout → server invalidates refresh token
Back to questions

5. Refresh Tokens Internally

Stored in httpOnly cookie (not JS-accessible). When access token expires, browser automatically sends cookie to the refresh endpoint. Server validates it, invalidates the old refresh token (rotation), and issues new tokens. This prevents replay attacks.

Back to questions

6. Frontend Security Vulnerabilities

AttackWhat it doesFix
XSSInject malicious scriptsSanitize input, CSP headers
CSRFTrick user into unwanted actionsCSRF tokens, SameSite cookies
ClickjackingHidden iframe tricks clicksX-Frame-Options: DENY
Outdated depsKnown vulnerabilities in packagesnpm audit, Snyk, Dependabot
Back to questions

Node Backend — Answers

1. Scalable REST API

Structure: routes → controllers → services → DB (separation of concerns). Add middleware for auth + validation. Use pagination for list endpoints. Add rate limiting (express-rate-limit). Log with Morgan/Winston.

Back to questions

2. JWT Backend

Login → sign access + refresh tokens → middleware verifies access token on every protected route → POST /refresh endpoint validates refresh token and issues new pair → POST /logout invalidates refresh token in DB.

Back to questions

3. Backend Caching

Redis for frequently read data (user sessions, product listings). Set a TTL (time-to-live). On write operations, invalidate or update the relevant cache key. Use cache-aside pattern: check cache first, miss → DB → populate cache.

Back to questions

4. SQL vs NoSQL

SQL (MySQL / PostgreSQL)NoSQL (MongoDB)
StructureFixed tables + schemaFlexible documents
RelationsJOINs, foreign keysEmbedded docs or refs
Best forBanking, e-commerceSocial media, real-time
ScalingVerticalHorizontal (sharding)
Back to questions

5. Indexing

Create indexes on columns you frequently filter/search/join → speeds up reads dramatically. Composite index for multi-column queries.

Don't over-index: each index slows down writes (INSERT/UPDATE/DELETE) and takes storage.

Back to questions

6. Scalable Architecture

  • E-commerce: microservices (users, products, orders), message queue (RabbitMQ/Kafka) for order processing, Redis cache, CDN for images.
  • Chat app: WebSocket server (Socket.io), MongoDB for message storage, Redis pub/sub for multi-server broadcast.
Back to questions

DSA DSA — Answers

1. Second Largest — O(n)

function secondLargest(arr) {
  let first = -Infinity, second = -Infinity;
  for (const n of arr) {
    if (n > first) { second = first; first = n; }
    else if (n > second && n !== first) second = n;
  }
  return second;
}
Back to questions

2. Kadane's Algorithm (Max Subarray)

function maxSum(arr) {
  let max = arr[0], current = arr[0];
  for (let i = 1; i < arr.length; i++) {
    current = Math.max(arr[i], current + arr[i]);  // extend or restart
    max = Math.max(max, current);
  }
  return max;
}
Back to questions

3. Sliding Window Maximum

Use a deque (double-ended queue) of indices. Keep it in descending order of values. Remove indices that are out of the window. Front of deque is always the max for current window.

function maxSlidingWindow(nums, k) {
  const dq = [], result = [];
  for (let i = 0; i < nums.length; i++) {
    while (dq.length && dq[0] < i - k + 1) dq.shift();  // out of window
    while (dq.length && nums[dq[dq.length-1]] < nums[i]) dq.pop();  // smaller
    dq.push(i);
    if (i >= k - 1) result.push(nums[dq[0]]);
  }
  return result;
}
Back to questions

4. Merge K Sorted Lists

Use a min-heap. Push the head node of each list into the heap. Each step: extract the minimum, add to result, push that node's next into the heap. Time: O(N log k).

Simple approach (JS): collect all values → sort → rebuild linked list. Time: O(N log N).

Back to questions

5. Detect Cycle — Floyd's Algorithm

function hasCycle(head) {
  let slow = head, fast = head;
  while (fast && fast.next) {
    slow = slow.next;        // 1 step
    fast = fast.next.next;   // 2 steps
    if (slow === fast) return true;
  }
  return false;
}
Back to questions

6. Longest Palindromic Substring

For each character, expand outward while left and right characters match. Check both odd-length (center = one char) and even-length (center = two chars) palindromes.

function longestPalindrome(s) {
  let res = "";
  for (let i = 0; i < s.length; i++) {
    for (const [l, r] of [[i, i], [i, i+1]]) {
      let lo = l, hi = r;
      while (lo >= 0 && hi < s.length && s[lo] === s[hi]) { lo--; hi++; }
      if (hi - lo - 1 > res.length) res = s.slice(lo+1, hi);
    }
  }
  return res;
}
Back to questions

7. LRU Cache

Use a Map — it preserves insertion order. On get: delete + re-insert to move to end (most recent). On put: if full, delete the first key (least recently used).

class LRUCache {
  constructor(cap) { this.cap = cap; this.cache = new Map(); }
  get(k) {
    if (!this.cache.has(k)) return -1;
    const v = this.cache.get(k);
    this.cache.delete(k);
    this.cache.set(k, v);  // move to end (most recent)
    return v;
  }
  put(k, v) {
    this.cache.delete(k);
    if (this.cache.size >= this.cap)
      this.cache.delete(this.cache.keys().next().value);  // remove LRU
    this.cache.set(k, v);
  }
}
Back to questions

8. Remove Duplicates by Key

function unique(arr, key) {
  const seen = new Set();
  return arr.filter(item =>
    seen.has(item[key]) ? false : (seen.add(item[key]), true)
  );
}
// unique([{id:1,name:"A"},{id:1,name:"B"},{id:2,name:"C"}], "id")
// → [{id:1,name:"A"}, {id:2,name:"C"}]
Back to questions

Debug Scenario-Based — Answers

1. Duplicate API Calls

  • Check useEffect dependency array — missing or wrong deps cause multiple runs.
  • React StrictMode double-invokes effects in dev — expected, not a bug.
  • Add debouncing to user-triggered calls.
  • Use AbortController to cancel duplicate in-flight requests.
  • Add an in-progress flag or use TanStack Query (deduplicates by default).
Back to questions

2. Works in Staging, Fails in Prod

  • Bundle size: prod has minification — check source maps, unexpected code paths.
  • Memory leaks: use Chrome DevTools Memory tab under real traffic patterns.
  • CDN caching stale JS: ensure filenames are cache-busted (content hash).
  • Hydration mismatch: check for window/Date usage in render paths.
  • Environment variables: verify prod env vars match staging.
Back to questions

3. Bundle Slow After Deployment

  • Run Lighthouse before/after to isolate the change.
  • Use webpack-bundle-analyzer — find what's new and large.
  • Check for missing code splitting on new routes.
  • Verify gzip/brotli is still enabled in server config.
  • Check if a new dependency pulled in a heavy transitive dep.
Back to questions

4. Too Many Re-renders

  • Open React Profiler → record interaction → see which components render and how long.
  • Wrap expensive components with React.memo.
  • Memoize callback props with useCallback, computed values with useMemo.
  • Move state down — don't lift state higher than necessary.
  • Split Context — one context causing mass re-renders → split into separate ones.
Back to questions

5. Real-time Dashboard Failures

ProblemSolution
WebSocket disconnectsAuto-reconnect with exponential backoff, show "reconnecting" state
API rate limits hitQueue requests, increase cache TTL, batch updates
Browser tab crashesPersist last known state to localStorage, restore on reload
Traffic spikes 10×CDN + load balancer, serve stale cached data, throttle updates to clients
Back to questions

HR Behavioral — Answers

Always use STAR format: Situation → Task → Action → Result

1. Challenging Production Bug

Structure: What broke and how it impacted users → how you found the root cause (tools used) → exactly what you fixed → what you learned or put in place to prevent recurrence.

Back to questions

2. Code Reviews & Mentoring

Reviews: focus on logic correctness and readability, give actionable suggestions (not criticism), ask questions rather than stating mistakes. Mentoring: pair programming, start with smaller tasks and increase complexity, explain the why not just the what.

Back to questions

3. Conflicting Priorities

List tasks by business impact and urgency → communicate transparently with stakeholders about trade-offs → break large work into smaller deliverables so something ships → escalate if timelines conflict at an organizational level.

Back to questions

4. Requirement Changes During Sprint

Assess impact on timeline and scope → discuss with PM immediately → small change: accommodate. Large change: negotiate next sprint. Document the change and update estimates. Avoid gold-plating — build only what's agreed.

Back to questions

5. Technical Disagreements

Listen fully to all perspectives → argue with data and concrete examples, not opinions → build a small prototype if the trade-off is unclear → once a team decision is made, commit to it fully even if it wasn't your preference.

Back to questions

6. Performance vs Feature Delivery

Performance IS a feature — slow apps lose users. Set measurable budgets (LCP < 2.5s, bundle < 200KB). Prioritize performance fixes that directly impact user retention or conversion. Automate perf checks in CI so they don't slip silently.

Back to questions

7. Tech Debt vs Features

Dedicate ~20% of each sprint to tech debt. Prioritize debt that blocks feature work or causes recurring bugs. Frame it to stakeholders as an investment: "fixing this now saves 3 days per sprint." Don't touch debt that isn't causing pain.

Back to questions

8. Explain to Non-Tech Stakeholders

Use simple analogies ("slow query = finding one book in an unsorted library vs. a catalogued one"). Focus on business impact: time saved, cost reduced, risk avoided. Use diagrams. Avoid jargon. Confirm they understood before moving on.

Back to questions

9. Most Challenging Task

Pick a real example with genuine complexity. Cover: the specific technical challenge → constraints you were working under → the approach you chose and why → what the outcome was → what you'd do differently. Show ownership.

Back to questions

10. End-to-End Project

Cover: problem it solves → architecture and tech stack choices (and why) → biggest technical challenges → how you handled performance → deployment and monitoring → team structure → what you'd improve now.

Back to questions

11. Angular to React Migration

Why: better developer ecosystem, component model, hooks simplicity, team hiring pool. Challenges: migrating incrementally (micro-frontend boundary between Angular and React), retraining team, re-implementing routing/state management, regression testing.

Back to questions

12. Team Conflicts

First understand their constraint (designers optimize for UX, backend for reliability — both valid). Find the shared goal. Propose a solution that addresses both concerns. Back proposals with data. If still stuck, involve a PM or tech lead as neutral mediator.

Back to questions

Good luck with your interviews! 🚀