Curated interview practice questions with answers. These are practice scenarios, not a verified list of past interview questions.
About Zomato hiring for React JS roles
Zomato is an Indian food delivery and restaurant discovery platform, operating under the listed parent Eternal Ltd alongside Blinkit quick commerce and District. Its tech and analytics teams work on delivery logistics, restaurant listings, ads and customer experience. It hires for software engineers, SDETs, product and business analysts, and data scientists.
For React JS roles, this Zomato practice set focuses most on React Fundamentals (6), Routing and Forms (6), Testing and Debugging (4), Props and State (4). It has 2 easy, 24 medium, 4 hard questions, so you can start easy and work up to the harder ones.
Company type
E-commerce & consumer tech
Headquarters
Gurugram, India
Main India offices
Gurugram
Zomato React JS interview process
Online assessment or assignment
Technical or case round
Hiring manager round
Culture fit round
Typical pattern based on public candidate experiences. Rounds vary by role, team and year.
Solved for ZomatoStart 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.
✓ 3 questions free • Unlock the rest in seconds
01
What is a Higher-Order Component and is it still used?
A Higher-Order Component is a function that takes a component and returns a new component with extra behaviour, for example withAuth(Profile) that redirects unauthenticated users. HOCs were common for sharing logic like routing or Redux connect. Today custom hooks are preferred because they avoid wrapper nesting, prop name collisions and confusing component trees. You will still see HOCs in older codebases.
An error boundary catches errors thrown while rendering its children and shows a fallback UI. It must be a class component (or use the react-error-boundary package).
class ErrorBoundary extends React.Component {
state = { hasError: false };
static getDerivedStateFromError() {
return { hasError: true };
}
componentDidCatch(error, info) {
logError(error, info.componentStack);
}
render() {
return this.state.hasError ? <p>Something went wrong</p> : this.props.children;
}
}
It does not catch errors in event handlers or async code.
React wraps native browser events in a SyntheticEvent object that has the same interface (preventDefault, stopPropagation, target) across browsers. Since React 17, listeners are attached to the root container instead of document, which makes it safer to mix multiple React versions. Event pooling was removed, so you can read event properties asynchronously. Handlers are passed as functions, like onClick={handleClick}.
04
Tell me about a time you had to learn a new tool or library quickly.
Situation: our project needed to switch from Jest to Vitest with a week's notice. Task: migrate around 300 tests. Action: I read the official migration guide, migrated one folder first to discover patterns, wrote a codemod for jest.fn to vi.fn replacements and documented gotchas for the team. Result: we finished in four days, test runs became much faster, and the guide helped others with later work.
05
What is the difference between getBy, queryBy and findBy queries?
getBy returns the element or throws immediately if it is missing, so use it when the element should exist. queryBy returns null instead of throwing, which is the right choice to assert something is not present: expect(screen.queryByText('Error')).not.toBeInTheDocument(). findBy returns a promise and retries until the element appears or times out, used for content that appears after async work. Each has an AllBy variant for multiple elements.
06
Your team's old codebase uses PropTypes and is upgrading to React 19. What would you recommend for checking prop types?
PropTypes checks props at runtime in development and was removed from the React package in React 19, so it now needs the separate prop-types library and is ignored silently. TypeScript checks types at compile time, gives editor autocompletion, and catches errors before code runs. Most new React projects in India and abroad use TypeScript, and many job descriptions now list it as required.
07
Show a Server Function used to handle a form in Next.js.
A function marked 'use server' runs on the server and can be passed to a form action.
// app/actions.ts
'use server';
import { revalidatePath } from 'next/cache';
export async function addTodo(formData: FormData) {
const title = String(formData.get('title'));
await db.todo.create({ data: { title } });
revalidatePath('/todos');
}
// app/todos/page.tsx
<form action={addTodo}>
<input name="title" required />
<button>Add</button>
</form>
Always validate input and check authorisation inside the function.
08
You import a component and get the error 'Element type is invalid: expected a string or a class/function but got undefined'. How do you debug it?
This almost always means the import does not match the export. If the file uses export default Header, import it as import Header from './Header'. If it uses export function Header, import it as import { Header } from './Header'. Also check the file path, circular imports and that the component name starts with a capital letter. Logging the imported value quickly confirms it is undefined.
Use vi.mock with a factory, then control return values per test.
import { vi } from 'vitest';
import { getProfile } from './api';
vi.mock('./api', () => ({
getProfile: vi.fn()
}));
test('shows name', async () => {
getProfile.mockResolvedValue({ name: 'Ravi' });
render(<Profile />);
expect(await screen.findByText('Ravi')).toBeInTheDocument();
});
In Jest, the same pattern uses jest.mock and jest.fn.
10
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.
11
What is lazy initialisation in useState and when should you use it?
If the initial value is expensive to compute, pass a function instead of the value. React calls it only on the first render.
// runs on every render (wasteful)
const [data, setData] = useState(JSON.parse(localStorage.getItem('cart')));
// runs once
const [data, setData] = useState(() =>
JSON.parse(localStorage.getItem('cart') ?? '[]')
);
In data or framework mode, a route can define a loader that fetches data before the route renders, and an action that handles form submissions or mutations for that route. Components read data with useLoaderData. After an action runs, the router automatically revalidates loaders so the UI shows fresh data. This moves data fetching out of effects and avoids request waterfalls between parent and child components.
13
A junior notices that every child component re-renders when the parent's state changes, even when their props did not change. How do you explain this?
By default, when a component renders, React re-renders all of its children, because it cannot know whether they depend on something else. Re-rendering is usually cheap since only real changes reach the DOM. If a child is expensive, wrap it in React.memo and keep its props stable with useCallback or useMemo, or let the React Compiler memoise automatically. Moving state down also helps.
14
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.
15
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.
16
Why should you use the functional form of setState? Show an example.
State updates are scheduled, and each render sees a snapshot of state. If you call setCount(count + 1) several times in one handler, all calls read the same old value. The updater function receives the latest pending value.
function addThree() {
setCount(c => c + 1);
setCount(c => c + 1);
setCount(c => c + 1);
}
// count increases by 3, not 1
17
A teammate wraps every function in useCallback and every value in useMemo for performance. When should you not memoise, and what feedback would you give?
Memoisation has costs: extra memory, comparisons on every render and more complex code. Skip it for cheap calculations, components that rarely re-render, and props that change every render anyway. Memoising everything by default also hides design problems like state placed too high. Use the profiler to find real bottlenecks first. With the React Compiler, manual memoisation is mostly needed only as an escape hatch.
18
A developer writes key={Math.random()} to silence the missing key warning. What problem does this create?
A new random key on every render tells React each item is brand new, so it unmounts and remounts every row each time. This destroys component state such as typed input and focus, re-runs effects and is very slow for large lists. Keys must be stable and unique, ideally an id from the data. If items have no id, generate ids once when the data is created.
19
Your team uses the array index as key in a todo list and users report that checkboxes get ticked on the wrong item after deleting a row. What is happening?
When an item is deleted, every later item shifts to a new index, so React matches old state and DOM nodes to the wrong items. Uncontrolled inputs and component state stay attached to the index, not the data. The fix is to use a stable unique id from the data as the key. Index keys are only safe for static lists that never reorder, filter or delete.
20
Users lose their typed data when they accidentally click another menu link. How would you warn them about unsaved changes?
Track a dirty flag, for example formState.isDirty from React Hook Form. For in-app navigation, use React Router's useBlocker to block the transition and show a confirm dialog. For tab close or refresh, add a beforeunload listener while the form is dirty, and remove it in the effect cleanup. Also consider autosaving drafts, which is often a better user experience than blocking.
21
How would you build and maintain a shared component library for several React apps?
Start with design tokens for colours, spacing and typography, and build accessible primitives, often on top of headless libraries like Radix UI or React Aria. Document components in Storybook with usage examples, add visual regression and accessibility tests, and publish versioned packages from a monorepo with semantic versioning and changelogs. Keep APIs small and composable, and collect feedback from consuming teams before breaking changes.
22
A user types into an input inside a list row, then sorts the list, and the typed text appears in a different row. How would you fix this?
The rows are probably keyed by index or by a value that changes after sorting, so React keeps the DOM input in the same position while the data moves. Give each row a stable key from the data, such as the record id. Better still, make the input controlled and store its value in state keyed by id, so the text always follows the correct record.
23
When would you add end-to-end tests with Playwright or Cypress?
Add E2E tests for critical business flows that cross many components and the backend, such as signup, login, search, add to cart and payment. They run in real browsers and catch integration issues unit tests miss. They are slower and more brittle, so keep them few and focused, use stable selectors like roles or data-testid, seed test data and run them in CI on every pull request.
24
How do you fetch data in a Next.js App Router page?
Make the page an async Server Component and await data directly.
// app/products/[id]/page.tsx
export default async function ProductPage({ params }) {
const { id } = await params;
const product = await getProduct(id);
if (!product) notFound();
return (
<main>
<h1>{product.name}</h1>
<AddToCartButton id={id} />
</main>
);
}
AddToCartButton is a Client Component. In recent Next.js versions params is a promise.
In useMutation, use onMutate to cancel ongoing queries, save the previous cache data and update the cache with the expected result. In onError, restore the saved snapshot and show an error toast. In onSettled, invalidate the query so the cache syncs with the server. This makes actions like toggling a favourite feel instant while keeping data correct if the server rejects the change.
Store the wizard data in a parent component, a reducer, or a small store, not inside each step, because step components unmount when hidden. Each step receives its slice and an update callback. Validate each step before moving forward, and optionally save drafts to sessionStorage or the server so a refresh does not lose progress. The current step can also live in the URL for back-button support.
29
Five components on one page each fetch the same user profile, causing duplicate API calls. How would you fix this?
Lift the data fetching into a shared cache instead of each component fetching on its own. With TanStack Query or RTK Query, all components using the same query key share one request and one cached result, and get updates together. Alternatively, fetch once in a parent or route loader and pass data down. This also removes inconsistent loading spinners across the page.
In React 19 you can pass a function to a form's action prop: <form action={saveAddress}>. React calls it with the FormData when the form submits, runs it inside a transition, tracks pending state and resets uncontrolled fields after success. Combined with useActionState for results and useFormStatus for button state, this removes manual onSubmit, preventDefault and loading flags. In Next.js the action can be a Server Function.
Tips to crack the Zomato React JS interview
Practise product and business cases about restaurant ratings, delivery times or Blinkit order growth with clear metrics.
Revise SQL and Excel well, since analyst assignments often involve cleaning order data and presenting insights.
Follow Zomato and Eternal shareholder letters, which openly explain business priorities and are useful for interview discussion.
Keep a one-minute story ready for every project on your CV: problem, your part, tools, result.
Practise the hard questions on this page aloud; Zomato interviewers usually ask follow-ups on your first answer.
Frequently asked questions
How many rounds are there in the Zomato React JS interview?
Candidates usually go through 4 stages: Online assessment or assignment; Technical or case round; Hiring manager round; Culture fit round. The exact rounds change with the role, team, location and your experience, so confirm the process with the recruiter.
Which topics should I prepare for the Zomato React JS interview?
This practice set leans on React Fundamentals (6), Routing and Forms (6), Testing and Debugging (4), Props and State (4). Revise those first, then practise explaining one or two of your own projects end to end, because most Zomato interviewers ask you to walk through real work.
Are these the exact questions asked at Zomato?
No. These are curated practice questions that match the skills and difficulty usually tested in e-commerce & consumer tech interviews like Zomato's. They are not a leaked or verified list of past questions.
Where does Zomato hire React JS professionals in India?
Zomato has large teams in Gurugram. Openings and locations change often, so check the Zomato careers page and filter by city and experience.