36 practice questions with answers for React JS interviews in Ahmedabad.
React JS jobs in Ahmedabad
Ahmedabad and GIFT City have a growing market for IT services, fintech and product start-ups. Companies here value hands-on skills and the ability to work across tools, especially in smaller teams.
Below are 36 questions that match the mix of service, product and domain employers hiring react developers in Ahmedabad.
Solved for AhmedabadStart practicing
3 QUESTIONS FREESign up to unlock the full question bank and track your progress.Unlock every question and answer, then continue practising company-wise and package-wise.
React Hook Form registers inputs as uncontrolled by default and reads values through refs, so typing does not re-render the whole form. This makes large forms fast. It provides validation, error messages, field arrays for dynamic rows, and integrates with Zod or Yup through resolvers. It has a small bundle and works with UI libraries through a Controller component for custom controlled inputs.
Tree shaking is dead code elimination done by bundlers like Rollup (used by Vite), esbuild and webpack. They analyse ES module import and export statements and drop exports that are never used. It works only with static ESM syntax, not CommonJS require, and can be blocked by modules with side effects. Importing import { debounce } from 'lodash-es' instead of the whole lodash library keeps the bundle small.
03
A cart page keeps the selected item object in state and also the items array. After editing the item's quantity, the details panel shows the old quantity. Why?
The selected item is a copy duplicated from the array, so updating the array does not update the copy. This breaks the single source of truth. Store only selectedId in state and derive the item during render: const selected = items.find(i => i.id === selectedId). Now there is one place where each item lives, and every view stays in sync automatically.
04
A junior developer is confused about when to use useEffect. How would you explain it and help them?
Situation: a new joiner was putting almost all logic into effects, causing bugs. Task: help them build the right mental model. Action: I explained that effects sync with outside systems, while calculations go in render and user actions go in handlers. We refactored one of their components together and I shared the react.dev article on avoiding effects. Result: their next PR had no unnecessary effects.
05
After adding an AuthContext at the root, profiling shows the whole app re-rendering every few seconds. What would you check?
Check what the provider value is and what updates it. Likely the value is a new object each render, or it includes fast-changing data such as a token refresh timer or a clock. Memoise the value with useMemo, move frequently changing data out of the context, and split it into separate contexts, so components reading only the user do not re-render when unrelated fields change.
Server Components run only on the server or at build time. They can be async, read databases or files directly and send rendered output to the client without shipping their JavaScript, which reduces bundle size. They cannot use state, effects or browser APIs. Client Components, marked with 'use client', handle interactivity. Server Components can render Client Components and pass them serialisable props.
07
All unit tests passed, but users found that the delete button did nothing. The tests were checking that a handleDelete function was called. What went wrong?
The tests checked implementation details instead of user-visible behaviour. A mocked handler being called says nothing about whether the item actually disappears or the API is hit. Rewrite the test to click the button by role, mock the API with MSW and assert the item is removed from the screen. Behaviour-focused tests survive refactoring and catch real bugs like a broken wiring.
useSyncExternalStore subscribes a component to an external, non-React data source, like a browser API or a custom store, in a way that is safe with concurrent rendering. You give it a subscribe function and a getSnapshot function, and optionally getServerSnapshot. It prevents tearing, where parts of the UI show different values of the same store. Libraries like Redux and Zustand use it internally.
09
On a profile edit page, when you switch from one user to another the form still shows the old user's typed values. How can you reset it cleanly?
React preserves state when the same component stays at the same position in the tree. Give the form a key tied to the user, like <ProfileForm key={user.id} user={user} />. When the key changes, React unmounts the old form and mounts a fresh one with new initial state. This is cleaner than writing an effect that manually resets every field when the user prop changes.
10
A new mid-sized dashboard project is starting. How would you decide between Context, Redux Toolkit and Zustand?
First separate server state, which I would handle with TanStack Query or RTK Query. For remaining client state, local useState covers most needs. Context suits rarely changing values like theme or auth. If there is complex shared state with many actions, strict patterns, large teams and need for DevTools time travel, Redux Toolkit fits. For simpler shared state with less boilerplate, Zustand is a good choice.
11
What is the difference between useMemo and useCallback?
useMemo caches the result of a calculation between renders, like a filtered list: useMemo(() => filter(items, q), [items, q]). useCallback caches a function definition itself: useCallback(fn, deps), which equals useMemo(() => fn, deps). Both are performance tools, useful when passing values to React.memo children or effect dependencies. With the React Compiler enabled, much of this manual memoisation becomes unnecessary.
Prop drilling is passing props through several layers of components that do not use them, only to reach a deeply nested child. It makes code noisy and hard to refactor. Solutions include component composition (passing JSX as children so intermediate layers do not need the data), the Context API for app-wide values like theme or user, and state libraries such as Zustand or Redux Toolkit for complex shared state.
The React Compiler, released as stable version 1.0 in late 2025, is a build-time tool (Babel plugin, also integrated in Vite and Next.js setups) that automatically memoises components and values. It analyses your code and inserts caching similar to useMemo, useCallback and React.memo, so developers write plain code. It requires following the rules of React, such as pure rendering, and can be adopted gradually per directory.
14
How do you analyse and reduce JavaScript bundle size?
Generate a visual report with rollup-plugin-visualizer in Vite or @next/bundle-analyzer in Next.js. Look for large dependencies, duplicate packages and code that loads on every page. Fixes include importing only what you need, replacing heavy libraries such as moment with date-fns or dayjs, lazy loading routes and rarely used components, and checking that libraries support tree shaking. Track size in CI to prevent regressions.
Render props means passing a function as a prop that the component calls to decide what to render, for example <MouseTracker render={pos => <Cursor pos={pos} />} />. It lets a component share its state or behaviour while the caller controls the UI. Like HOCs, it has mostly been replaced by custom hooks, but libraries for forms and virtualised lists still expose render-prop or children-as-function APIs.
Install the Redux DevTools browser extension; configureStore enables it automatically in development. You can see every dispatched action, the state before and after, the diff, and jump back in time to earlier states. Check whether the expected action was dispatched, whether its payload is correct and whether the reducer updated the right slice. For selectors, log their output or use the React DevTools profiler.
17
An accessibility audit says your signup form fails screen reader checks. What would you fix to make the form accessible?
Link every input to a visible label using htmlFor and id (useId helps), use correct input types, and mark required fields. Show errors as text, connect them with aria-describedby and set aria-invalid on failing fields. Move focus to the first error on submit, keep everything keyboard operable and do not rely on colour alone. Use native button and form elements instead of clickable divs.
Batching means React groups several state updates into one re-render. Before React 18 this only happened inside React event handlers. With createRoot, updates inside promises, setTimeout and native event handlers are also batched automatically. This reduces unnecessary renders. If you truly need a synchronous DOM update in between, you can use flushSync from react-dom, but that is rarely needed.
useRef returns a mutable object { current } that persists across renders without causing a re-render when changed. It has two main uses: holding a reference to a DOM node, for example to focus an input, and storing mutable values like timer ids, previous values or flags that should not trigger rendering. Do not read or write ref.current during rendering, except for lazy initialisation.
20
A developer sends an analytics event inside a useEffect that watches a 'submitted' state flag. Is this a good pattern?
No. Logic caused by a specific user action belongs in the event handler, not in an effect. Setting a flag and reacting in an effect adds an extra render, is harder to follow and can fire again on remount in StrictMode. Call sendAnalytics directly in handleSubmit. Effects are for synchronising with external systems because the component is displayed, not for responding to events.
21
Your team has hundreds of snapshot tests that developers update blindly whenever they fail. What are the drawbacks of snapshot tests and what would you suggest?
A snapshot test saves the rendered output to a file and fails when future output differs. It is quick to write and catches unexpected changes. Drawbacks: large snapshots are hard to review, developers often blindly update them, and they fail on harmless markup changes while saying nothing about behaviour. Use small, focused inline snapshots for stable output, and prefer behaviour assertions for most component tests.
22
Your React app works locally, but after deployment refreshing /dashboard gives a 404 from the server. Why, and how do you fix it?
The server looks for a real file at /dashboard, which does not exist because routing happens in the browser. Configure the server to return index.html for all unknown paths: a rewrite rule in Nginx (try_files $uri /index.html), a _redirects or rewrites setting on static hosts, or a fallback in Express. Alternatively, use a framework with server routing. HashRouter also avoids it but gives ugly URLs.
23
What is the guiding philosophy of React Testing Library?
React Testing Library encourages testing components the way users use them, not their internal implementation. You find elements by role, label or text, interact with them through user events and assert what appears on screen. You avoid checking state variables or component instances. Its motto is that the more your tests resemble the way your software is used, the more confidence they give you, and refactors do not break them.
24
How do you track errors that happen in production React apps?
Use an error monitoring tool such as Sentry, which captures exceptions with stack traces, browser and user context. Upload source maps during the build so minified stack traces map back to your source, but do not serve them publicly. Wrap major sections in error boundaries that report errors and show friendly fallbacks. Add release tags so you can see which deployment introduced a bug.
25
Tell me about a React project you built and the hardest problem you solved in it.
Situation: in my final year I built a hostel complaint portal with React, Vite and a Node API. Task: the complaint list became slow and buggy when filters changed. Action: I found I was storing filtered data in state and syncing it with effects, so I derived it during render with useMemo and fixed missing keys. Result: bugs disappeared, the page felt instant, and I learned to keep state minimal.
26
A search box fetches results on every keystroke and sometimes shows results for an older query. How do you fix this race condition?
Responses can arrive out of order, so a slow old request overwrites newer results. Cancel or ignore stale requests in the effect cleanup.
useEffect(() => {
const ctrl = new AbortController();
fetch(`/api/search?q=${q}`, { signal: ctrl.signal })
.then(r => r.json())
.then(setResults)
.catch(() => {});
return () => ctrl.abort();
}, [q]);
Also debounce the input, or use TanStack Query which handles this for you.
CSR (client-side rendering) sends a minimal HTML shell and renders everything in the browser. SSR (server-side rendering) generates HTML on each request, good for personalised or fast-changing pages. SSG (static site generation) builds HTML at build time, fastest for pages that rarely change like blogs. ISR (incremental static regeneration) serves static pages but regenerates them in the background after a time or on demand, mixing speed with freshness.
28
What is the difference between the App Router and the Pages Router in Next.js?
The Pages Router uses the pages directory with getServerSideProps and getStaticProps for data. The App Router, the recommended default, uses the app directory with nested layouts, React Server Components by default, streaming with loading.js, error.js boundaries and Server Functions. Data is fetched directly in async server components. Many older projects still use Pages Router, and both can coexist during migration.
29
What is Next.js and why would you use it instead of plain React?
Next.js is a React framework that adds file-based routing, server-side rendering, static generation, React Server Components, API endpoints, image and font optimisation and production build tooling. Plain React with Vite is a client-side library setup where you choose routing and data fetching yourself. Next.js is preferred when you need SEO, fast first load, server logic close to the UI or a full-stack app in one codebase.
30
How do you handle a tight deadline when you know the code is not perfect?
Situation: a festive sale banner feature had to go live in two days. Task: ship safely without gold-plating. Action: I listed must-haves with the product owner, wrote tests for the critical checkout path, kept a simple implementation and logged clear tech-debt tickets for refactoring. Result: we launched on time with no incidents, and I cleaned up the code in the next sprint as planned.
31
How do you persist part of your state, like the cart, across page reloads?
Save it to localStorage and read it on startup. With Zustand, the persist middleware does this.
import { persist } from 'zustand/middleware';
const useCart = create(persist(
set => ({ items: [], add: i => set(s => ({ items: [...s.items, i] })) }),
{ name: 'cart-storage' }
));
With Redux, use redux-persist or a store.subscribe that writes a throttled snapshot. Never store secrets like tokens in localStorage.
32
Write a custom hook to fetch data with loading and error states.
The pyramid says write many unit tests, fewer integration tests and very few end-to-end tests, because lower tests are fast and cheap. The testing trophy, popular for frontend, adds static analysis at the base and puts the most effort in integration tests, since they give the best confidence per cost. For React, I rely on TypeScript and ESLint, many component tests, some unit tests for logic and a few E2E tests.
The function you return from useEffect is the cleanup. React runs it before the effect runs again and when the component unmounts. Use it to clear timers, remove event listeners, close WebSocket connections, unsubscribe from stores or abort fetch requests. Without cleanup you get memory leaks, duplicate listeners and state updates on components that are no longer on the screen.
36
What are the risks of spreading all props like <Input {...props} />?
Spreading is convenient for wrapper components, but it can pass unknown attributes to DOM elements, causing console warnings, and it hides what the component actually accepts. It can also override props you set explicitly, depending on order. Prefer destructuring the props you use and spreading only the rest onto the underlying element, for example const { label, ...inputProps } = props.
Frequently asked questions
Which companies hire React JS professionals in Ahmedabad?
Companies with large offices in Ahmedabad include many IT services and product firms. Use their company pages below to practise employer-specific sets.
Are React JS interviews in Ahmedabad different from other cities?
The questions depend more on the company than the city. Ahmedabad's mix of employers decides the style: Companies here value hands-on skills and the ability to work across tools, especially in smaller teams
How do I find React JS jobs in Ahmedabad?
Shortlist companies with Ahmedabad offices, keep your CV focused on React JS projects, apply on company career pages and job portals with the Ahmedabad filter, and practise the questions on this page before each interview.