Hire React Developers in India
This page is about the person, not the project. If you are about to hire React developers in India for a product that already has users, what you are buying is judgement: where state lives, which re-render costs you a frame, and whether the codebase is still changeable in eighteen months. Below is how to screen for that, what the seniority labels really mean, and what the timezone gap actually costs.
What Does a React Engineer Actually Do All Day?
Very little of it is writing components. On a product past its first year, a React engineer spends most of the week deciding where a piece of state belongs, reading someone else's component to work out why it renders four times, and making a change that touches nine files without breaking the other eleven that import the same hook.
That is the skill you are hiring. React is small as a library. The hooks API fits on two pages and a capable JavaScript developer can learn it in a fortnight. What takes years is the architectural instinct underneath: knowing that a modal's open state belongs in the URL rather than a context, that a form with twenty fields should be uncontrolled until it needs to not be, that a data table with server-side sorting and client-side filtering has two sources of truth and one of them is going to drift.
A typical day on a mature codebase looks like this. An hour reading a ticket and the code around it. A pull request review where the comment that matters is not about naming but about a useEffect that synchronises two pieces of state which should have been one. A change to a shared component that needs a check on every consumer, because React gives you no compiler warning when a prop's meaning quietly shifts. A profiling session in React DevTools because a page got slower and nobody knows which commit did it. Then, maybe, some new UI.
How this differs from "a frontend developer"
The titles overlap and the market uses them interchangeably, which causes real hiring mistakes. A frontend developer, in the older sense, owns the browser layer: semantic markup, CSS architecture, layout across viewports, cross-browser quirks, and the visual result matching what the designer drew. That is a genuine discipline and it is not going away.
A React engineer owns something narrower and deeper: the component graph and the data flowing through it. Their work is judged on whether adding the fortieth screen is as cheap as adding the fourth. They will happily spend a day deleting a context provider. They think in terms of ownership, derivation and invalidation. Many of them write mediocre CSS, and they know it.
Both skills exist in one person often enough that you can hire for both, but you have to say so. A job description that reads "React developer, must have strong CSS and design sense" describes a product-focused engineer. One that reads "React developer, complex state, performance on large datasets" describes someone else entirely. Ask for the wrong one and you get a good engineer doing the wrong job, which is more expensive than a bad hire because it takes longer to notice.
The part nobody writes in the job ad
React codebases decay in a particular way. Not through bad code, mostly, but through accumulated state that nobody owns. A flag is added to a context because it was quick. A component takes a boolean prop, then another, then a variant string, and now it has fourteen possible renderings and two of them are broken. Data gets fetched in three places and cached in a fourth. None of this is a bug on the day it ships, and all of it makes the next change slower.
The engineers worth hiring are the ones who notice this happening and push back in code review, and who can explain why a change is a bad idea without saying "that is not the React way". If a candidate cannot criticise a design without appealing to authority, they will not defend your architecture when a deadline arrives.
Do You Actually Need Redux, and What Should You Ask About It?
More people search for a React Redux developer than for almost any other React skill combination, and a good share of them do not need Redux at all. Here is how to tell which group you are in, and what a candidate's answers reveal.
When Redux genuinely earns its place
Redux is a single, predictable, inspectable store with a strict update discipline. It pays for itself when several distant parts of the interface must agree on the same client-side truth, when you need to reconstruct how the application reached a broken state, and when the update logic itself is complicated enough that having every change flow through named actions is a debugging advantage rather than paperwork.
Concretely: a trading or logistics dashboard where one websocket message updates six panels. A multi-step configurator where step four can invalidate a choice made in step one. An editor with undo and redo, where the action log is the feature. A large application with several teams shipping into it, where the discoverability of a central store beats the flexibility of scattered hooks. In all of those, the ceremony buys you something.
When reaching for Redux is a signal to slow down
The most common misuse in the wild is Redux as an API cache. A developer writes a thunk that fetches a list, stores it, writes a loading boolean, an error field, and a selector, and then repeats that shape twenty-three times for twenty-three endpoints. Now half the store is a stale copy of the database, and refetching, deduplicating and invalidating it are all problems the team has to solve by hand.
That is server state, and it is not the same species as client state. Server state is owned elsewhere, arrives asynchronously, goes stale without telling you, and is shared between users. Client state is yours: which tab is open, what is typed in the filter box, whether the sidebar is collapsed. Mixing them into one store is the root of most of the Redux code I would not want to maintain.
So in an interview, ask what they would put in the store for a screen that lists orders with a search box and a detail drawer. If the answer starts with the orders, keep asking. If the answer is that the orders belong in a query cache and only the search text and the open drawer id are store material, you are talking to someone who has thought about this.
Redux Toolkit against the Redux people learned in 2018
Redux Toolkit is the version that should be in any current codebase, and the difference is not cosmetic. createSlice generates action creators and types from the reducer you write. Immer lets you write what looks like mutation while producing an immutable update, which removes an entire category of spread-operator bugs in nested state. configureStore sets up the DevTools connection and sensible middleware without a wiring file. createAsyncThunk handles the pending, fulfilled and rejected trio you would otherwise hand-roll. RTK Query, which ships in the same package, is a proper data-fetching and caching layer with tag-based invalidation, and it exists precisely because so many teams were misusing the store as a cache.
Legacy Redux looks different: string action constants in a separate file, hand-written switch reducers, connect with mapStateToProps and mapDispatchToProps, and often redux-saga carrying orchestration in generator functions. None of that is wrong, and plenty of it is still running profitably. But a candidate who only knows that style has not touched a modern Redux codebase, and a candidate who dismisses it has probably never had to maintain one. Ask which they have done. Ask what a saga is good at, and whether they would introduce one now. The honest answer is that sagas are excellent for long-running, cancellable, cross-action workflows and are heavy for anything else.
The modern alternatives, and where each one fits
TanStack Query handles server state: fetching, caching, background refetching, deduplication of identical in-flight requests, stale time, and invalidation on mutation. It is the right answer for most of what teams were putting in Redux. The concept a candidate must be able to explain is the difference between stale and inactive data, and why a cached query being marked stale does not mean it gets thrown away.
Zustand is a small store you consume through a hook with a selector, so a component only re-renders when the slice it selected changes. It gives you most of Redux's mental model with almost none of the setup, and it does not force actions. That freedom is the trade: nothing stops a team writing scattered setters and losing the discipline that made Redux useful in the first place.
Jotai works bottom up. State lives in atoms, atoms derive from other atoms, and components subscribe to exactly the atoms they read. It suits interfaces where state is naturally fine-grained, such as a canvas or a spreadsheet-like grid, and it is harder to reason about globally because there is no single object to inspect.
React Context is not a state manager and this is worth saying plainly, because the misunderstanding is expensive. Context is dependency injection for the component tree. Every consumer re-renders when the provider value changes, with no selector to narrow it, so putting frequently changing state in a context near the root of a large tree is a performance problem you will diagnose later at some cost. Context for a theme, a locale, a current user object that changes on login. Not for a form's live values.
useSyncExternalStore is the hook that exists so external stores can integrate with React's concurrent rendering without tearing. A candidate who knows why it exists understands something real about how React 18 renders. It is a fair senior-level question and an unfair one for a mid-level developer.
What to ask if you are specifically hiring for a Redux codebase
Start by describing your store honestly, then ask them to critique it. A candidate who has lived in Redux will ask three questions back within a minute: how normalised is the state, where does async live, and how many selectors compute derived data on every render. Those questions are the tell.
Then ask about normalisation. Storing entities keyed by id with arrays of ids for ordering is the pattern that keeps a large store sane, and it is also the pattern people skip because nesting is easier on day one. Ask what goes wrong when the same order object is embedded in three different lists. The answer, that updates have to be applied in three places and one of them will be missed, should come out without prompting.
Finally ask about reselect and memoised selectors: what happens when a selector returns a new array literal every call, and why that quietly defeats the memoisation the team thought they had. If your codebase is on legacy Redux and you want it modernised, ask how they would migrate incrementally, slice by slice, while shipping features. Anyone whose answer is a rewrite has not done it.
Hiring Redux Developers for a Store Somebody Else Wrote
Everything above is about whether to choose Redux. This is about the more common situation, where the choice was made years ago by a person who has since left, and you now need to hire Redux developers to look after what they built. Different brief, different candidate.
What the search usually means
Almost nobody looking for a React Redux developer is starting from an empty repository. Three situations produce that search and they want three different people.
The first is inheritance. A store exists, whoever designed it has gone, and the remaining team can add to it but cannot say why it is shaped the way it is. You need a reader.
The second is drag. Nothing is on fire. But every feature now costs a reducer change, a selector change, a middleware change and four test changes, delivery has visibly slowed, and somebody in a planning meeting has started using the word rewrite. You need a person who can work out which of those four changes was never necessary.
The third is a decision already taken on a product that does not exist yet. A lead has chosen Redux for something greenfield. What you want there is close to the opposite of a specialist: someone who will argue with the choice before implementing it, and who has the standing to lose that argument gracefully.
What you are actually buying
Reading. That is most of it.
Redux code is unusually legible line by line and unusually opaque in aggregate. Each reducer is a small pure function anybody can follow in a minute. The thing no reducer tells you is why the shape is what it is: which field exists because a screen needed it, which exists because an endpoint returned it, which is a workaround for a race condition that was properly fixed somewhere else two years ago and is now dead weight nobody dares remove. Reconstructing that intent out of reducers, selectors and a commit history is a specific and unglamorous skill, and it is the one you are paying for. Writing a new slice is not hard.
Which is why years on a CV tell you very little here. Six years of Redux means somebody has typed dispatch a great many times. Ask instead about the largest store they have worked inside, and what they took out of it. People who have done the maintenance job describe shape before they describe features, and they describe deletions with some pride.
What an inherited store usually has wrong
The same handful of things keep turning up, and none of them are exotic.
Derived data stored rather than computed. A total, a filtered list, a count of unread items, each written into the tree alongside the source it came from. Now two places can be right and one of them will not be. The tell is a reducer that updates three fields in response to a single event.
A tree shaped like the API. Whatever JSON the backend happened to send became the state, nesting and all. That holds until two endpoints return the same entity with different fields, after which the same record lives in the store twice with different contents depending on which screen loaded first.
Business rules that drifted into middleware. Something began as a logger. It grew a rule, then a redirect, then a conditional dispatch. A meaningful slice of your application's behaviour now lives in a function no test imports and no developer reads voluntarily.
A persistence layer nobody versioned. redux-persist or a hand-rolled equivalent writes state to local storage and rehydrates it on load. Reducers changed over the years. The saved shape did not. Returning users get a tree the code no longer expects, and the bug report reads that the app is broken for some people and fine for everyone else, which is the least actionable sentence in software.
Two providers. Somebody needed a store inside an embedded widget, added a second Provider, and now the tree has two sources of truth with the boundary between them written down nowhere.
Ask a candidate which of these they have personally found. Anyone who has spent real time in maintenance will add one you did not list.
Screening for this job specifically
Send them a reducer. A real one, out of your repository, names intact. Twenty minutes, three questions: what feature is this for, which of this state could be computed instead of stored, and what would you want to see before touching it.
Answers stratify fast. A weak candidate explains the syntax back to you. A competent one finds the derived field. A strong one asks who else reads this slice before answering anything, because they know the risk sits in the selectors and components downstream that assume its shape, not in the reducer you handed over.
Then ask about the dispatch they would refuse to write. Everyone who has maintained a large store has an action they think should never have existed, and it is almost always one named after a screen rather than after something that happened. Actions named for events keep a store readable for years. Actions named for the component that fired them weld your state tree to a user interface that is going to be redesigned.
Finish with a trap. Tell them the store has forty slices and ask how long a move to something modern would take. Any number is wrong. What you want back is a set of questions: how many of those slices are actually read, how many have tests, and can the team keep shipping features while the work happens. A migration that pauses delivery gets cancelled in week six, and the person who has done one knows it.
Where the hire sits on your team
Embedded, with review rights over anything that touches the store. Not a parallel workstream. Cleanup that runs beside feature development without seeing it gets quietly undone by the feature development, and the person doing the cleanup finds out at merge time, which is late and demoralising in equal measure.
How Do You Screen a React Developer in an Hour?
You cannot assess architecture in sixty minutes. You can find out whether someone has shipped React to real users, because shipped experience leaves marks. Each of these is a question with a wrong answer that sounds right.
Reconciliation and keys
Ask why using the array index as a key is a problem, and push until you get a concrete failure rather than "React needs unique keys". The real answer involves component identity: React matches children between renders by key, so if the list is reordered or an item is inserted at the top, the index-keyed elements keep their old component instances and any internal state, uncontrolled input values and focus stay attached to the wrong row. The classic demonstration is a list of rows each with a checkbox, sorted, where the checked rows are now the wrong ones.
Follow up by asking when an index key is fine. It is, for a static list that never reorders, never filters and never inserts. Someone who says index keys are always forbidden has learned a rule rather than a mechanism.
useEffect dependency arrays and cleanup
This is the single richest screening area in React, because it is where most production bugs live. Ask what the dependency array does, then ask what happens when a function defined in the component body is listed as a dependency. The answer is that it is a new reference on every render, so the effect runs every render, which is usually why someone reached for the empty array and lied to the linter.
Then ask about cleanup. An effect that subscribes, sets an interval, adds an event listener or starts a fetch has to return a cleanup function, and the reason is not tidiness: without it you get leaks and, more often, race conditions where a slow response for a previous parameter arrives after a fast one for the current parameter and overwrites it. Ask how they cancel a fetch. Acceptable answers are an AbortController passed to fetch and aborted in cleanup, or an ignore flag set in cleanup and checked before calling setState. Both are fine. No answer is not.
Finish with StrictMode. In development, React 18 and later mounts, unmounts and remounts components inside StrictMode, so effects run twice on purpose. A developer who has shipped will bring this up unprompted, usually with a story about a duplicated analytics event or a doubled API call that only happened locally. A developer who has not will think it is a bug in React.
Stale closures
The set piece: a component with a counter, a setInterval created inside a useEffect with an empty dependency array, and a callback that reads the state variable. Why does the counter stop at one? Because the interval callback closed over the state value from the first render and never sees a newer one. Ask for two fixes. The functional updater form, setCount(c => c + 1), is the clean one. A ref holding the latest value is the other, and it is the right tool when the callback needs several current values rather than one.
This question sorts candidates faster than anything else on the list, because stale closures are the bug that everyone who has written non-trivial React has personally lost an afternoon to, and nobody who has only followed a tutorial has met.
Memoisation, and when useMemo is noise
Ask when they would use useMemo. The bad answer is "to optimise expensive calculations", recited. The good answer includes the fact that memoisation is not free: you pay for the comparison of dependencies and the retained reference on every render, so wrapping a cheap expression makes the code slower and harder to read.
The two cases where it genuinely matters are a computation that is actually expensive, measured rather than assumed, and preserving referential identity for a value that feeds another hook's dependency array or a memoised child's props. That second case is the one people miss. Ask what happens when you wrap a child in React.memo and then pass it style={{margin: 8}} or an inline arrow function. Nothing happens, because a new object and a new function are created every render and the shallow comparison fails every time. A candidate who has profiled a real app will have this story.
It is worth asking their view on the React Compiler, which memoises automatically at build time. The interesting part is not whether they use it but whether they can say what it changes about the manual work, and whether they have actually run it against a codebase that breaks the rules of hooks rather than only read about it.
Controlled and uncontrolled components
Ask them to explain a controlled input and then to argue against using one. Controlled means React state is the source of truth and every keystroke is a state update and a re-render, which is fine for a login form and measurably bad for a form with sixty fields inside a large tree. Uncontrolled means the DOM holds the value and you read it through a ref or on submit.
This connects to library choice. React Hook Form is uncontrolled by default and subscribes at the field level, which is why it re-renders so little; Formik was controlled and became the reason several large forms felt sluggish. Ask which they have used at scale and what made them switch. Also ask what a "changing an uncontrolled input to be controlled" warning means, because that message appears when a value goes from undefined to a string, and everyone who has built forms has caused it.
Error boundaries
Ask what an error boundary catches and, more usefully, what it does not. It catches render errors, lifecycle errors and constructor errors in the tree below it. It does not catch errors inside event handlers, errors in asynchronous code such as a promise rejection or a setTimeout callback, or errors thrown in the boundary itself. Event handler errors need an ordinary try and catch, which surprises people.
Ask where they place boundaries. One at the root only means a single component failure blanks the whole application. Boundaries around each independently failing region, a dashboard widget, a route, a third-party embed, mean the rest of the page survives. Also worth asking: error boundaries are still class components in React itself, which is why most teams use the react-error-boundary package rather than writing their own.
Suspense, and what it does not do
Suspense is a boundary that renders a fallback while something below it is not ready. With React.lazy, that something is a code-split chunk. With data, it is a promise that a compatible library or framework knows how to throw and track. Suspense does not make an ordinary fetch inside useEffect suspend, and a candidate who thinks it does has read the headline and not the docs.
The useful follow-up is about placement: a Suspense boundary too high in the tree replaces the whole page with a spinner and produces a worse experience than the loading states you were trying to delete. The good pattern is boundaries close to the data, with skeletons that hold layout so nothing shifts when content arrives.
Hydration mismatches
Only relevant if you server-render, and essential if you do. A hydration mismatch happens when the HTML the server produced does not match what the client renders on the first pass. The usual causes are timestamps and Date formatting, Math.random, locale or timezone differences between server and browser, reading window or localStorage during render, invalid HTML nesting that the browser silently corrects such as a div inside a p, and browser extensions injecting nodes into the body.
Ask what the consequence is. It is not cosmetic: React discards the server markup for the mismatched tree and re-renders it on the client, which costs you the performance you were server-rendering to gain, and it often shows up as a visible flash. Ask what they do about content that is legitimately client-only. Rendering a stable placeholder on both sides and filling it after mount is the honest fix; suppressing the warning is not.
One question to end with
"Tell me about a React performance problem you diagnosed, and how you knew you had found it." The answer must contain a tool. React DevTools Profiler, the browser Performance panel, a flame chart, a long-task marker. If the story is "I added useMemo and it got better", they guessed. If the story is "the Profiler showed the provider re-rendering 400 components on every keystroke, so I moved the input state down into the field", you can stop the interview and start negotiating.
Junior, Mid, Senior, Staff: What the Labels Mean for React
Titles inflate everywhere and React is worse than most, because the library is easy to start with and the market rewards the word senior. These are the behavioural markers, not the years.
Junior
Builds a component from a design when the props are decided for them. Uses hooks correctly in the common cases and copies the patterns already in the codebase, which is exactly what you want at this level. Needs the state design handed to them. Will introduce a useEffect that mirrors one piece of state into another and will not see why that is a problem until someone shows them. Reviews take real time from a senior, and that cost is part of the hire, not an accident of it.
Mid
Owns a feature end to end: reads the API contract, decides component boundaries within the feature, handles loading, empty and error states without being asked, writes the tests. Knows the render behaviour well enough to avoid the obvious traps. Will still occasionally solve a problem with a context that should have been a prop, or reach for a state library where a URL parameter would do. Can be trusted alone on anything that does not change shared foundations.
Senior
Decides where state lives across features and defends the decision. Reads an unfamiliar codebase and can tell you within a day which parts are load-bearing. Profiles before optimising. Writes the shared component that four teams use and gets its API right the first time, or notices in review that a proposed prop is a design smell. Says no to work, with a reason. Handles the boring but decisive things: bundle size budgets, accessibility in the shared primitives, what happens on a slow network. On a small team this person is also your architect whether you call them that or not.
Staff and above
Works across teams and mostly through other people. Chooses the state management strategy for the organisation, then chooses when to stop changing it, which is the harder half. Runs the migration from an eight-year-old class-component codebase without stopping feature delivery. Sets the review standard, writes the codemod, decides that the design system is now a product with its own release cadence. You need one of these when React decisions are being made in three places and disagreeing. Below roughly twenty engineers, hiring at this level is usually premature.
How to check the label matches
Give the candidate a small piece of your real architecture and ask them to critique it. Juniors describe it back. Mids spot a specific bug. Seniors ask what constraints produced it before offering an opinion, and then name a trade-off you had actually argued about internally. That last reaction is not fakeable, and it is worth more than any take-home exercise.
The Adjacent Skills That Decide Whether the Hire Works
React on its own is not a job. These five surround it, and weakness in any of them shows up in your codebase within a month.
TypeScript
Most React work now happens in TypeScript, and the depth varies enormously between people who list it. The floor is typing props and state. The level you actually want includes generic components, discriminated unions to model states that cannot coexist, and correctly typed custom hooks including the tuple return with as const. Ask what unknown is for and why it is better than any at an API boundary. Ask how they type a component that forwards a ref. If your team is migrating a JavaScript codebase, ask how they would sequence it and whether they would turn on strict at the start or the end. Both answers are defensible; having no view is not. There is more on this in our page for teams looking to hire TypeScript developers in India.
Testing
React Testing Library is the standard and the reason is philosophical: it queries the DOM the way a user finds things, by role, label and text, which means the tests survive refactors that change component internals. Enzyme tested implementation details, and it also never received an official adapter for React 18, so a codebase still on Enzyme is stuck in a way that will cost you.
Screen for the difference between getBy, queryBy and findBy, because getting that wrong is why test suites become flaky. Ask how they handle network calls in tests: Mock Service Worker intercepts at the network layer and lets the real fetch code run, which is a much better default than mocking the fetch module. For end-to-end, Playwright and Cypress are both reasonable, with Playwright ahead on parallel execution and multi-browser coverage and Cypress ahead on the debugging experience for people who live in it daily. Vitest is now common on Vite projects and Jest remains everywhere else.
Build tooling
Create React App is no longer the recommended starting point and has not been maintained as such, so any candidate proposing it for a new project in this decade is out of date. Vite is the default for a client-rendered application. What matters at interview is not the tool but whether they can read a bundle: ask what they do when the main chunk crosses a size budget. The answer should include analysing the bundle, finding the accidental import of an entire icon or date library, splitting routes with dynamic imports, and checking whether a dependency ships an ES module build that actually tree-shakes. Ask how they would find out that a single date formatting library added 300 kilobytes. If they have never looked, they have never had to.
Accessibility
Single-page applications break accessibility in a specific way: there is no document load between views, so a screen reader user gets no announcement when the route changes and keyboard focus stays wherever it was. Fixing that means moving focus to the new view's heading and announcing the change in a live region. Almost nobody does it, and it is a fair question because the answer tells you whether they have ever tested with a screen reader or only run an automated checker.
The other markers: a div with an onClick and no role, no tabindex and no key handler is the most common failure in React code. Modals need focus trapping and restoration. Form fields need real labels rather than placeholders. eslint-plugin-jsx-a11y catches the static cases and misses everything dynamic. If WCAG 2.2 AA is a contractual requirement for you, say so in the brief, and ask which primitives they would build on, since Radix UI and React Aria have done the keyboard and ARIA work that hand-rolled components usually get wrong.
Core Web Vitals, and what React does to INP
Interaction to Next Paint replaced First Input Delay as a Core Web Vital in March 2024, and it is the metric React applications fail. The published thresholds are 200 milliseconds or less for good and above 500 for poor, measured at the 75th percentile of real user interactions. Unlike FID, INP measures the whole interaction, from input through processing to the next paint, which is exactly where a re-render cascade lives.
The React-specific causes are consistent. A controlled input near the top of a large tree re-renders hundreds of components per keystroke. A context provider holding fast-changing state re-renders every consumer. A long unvirtualised list re-renders in full when one row changes. Hydration on a large server-rendered page blocks the main thread while the user is already trying to click. The fixes are equally consistent: move state down to the component that owns it, split contexts, virtualise long lists with TanStack Virtual or react-window, mark non-urgent updates with useTransition or useDeferredValue so React can yield to input, and break up long tasks. Largest Contentful Paint at 2.5 seconds and Cumulative Layout Shift at 0.1 are the other two thresholds, and CLS is usually a skeleton that does not match the height of what replaces it.
React or Next.js? They Are Not Always the Same Hire
React is a library for rendering components. Next.js is a framework with a server, a router, a caching model, a build pipeline and opinions about all of them. The skills overlap heavily at the component level and diverge sharply above it, so the distinction belongs in your brief.
When plain React is the right answer
An authenticated application behind a login has little to gain from server rendering. Nobody is indexing it, the first paint matters less than the interaction speed once the shell is loaded, and a client-rendered app deployed as static files to a CDN is simpler to run and simpler to reason about. Internal tools, dashboards, admin panels and anything embedded in an existing page belong here. Pair React with React Router or TanStack Router, add TanStack Query for the data layer, and you have a stack a single strong engineer can own.
When you need the framework
Public pages that must rank, share well and load fast on a mid-range phone need HTML from the server. So does anything where the content changes on a schedule you want cached rather than recomputed. Next.js gives you file-based routing, several rendering strategies per route, image optimisation, and React Server Components, which run only on the server and never ship to the browser. That last one changes how you think about data: fetching happens in the component, on the server, without an API endpoint in between.
It also introduces failure modes a pure React engineer has not met. The client boundary is the main one: a server component cannot use hooks, state or event handlers, and the moment you add "use client" everything imported below it goes to the browser too. People discover this when a server-only dependency ends up in the client bundle or a secret leaks into it. The caching model is the second: knowing what is cached, for how long, and how to invalidate it, is a real part of the job and has changed across Next.js major versions, so ask which versions they have shipped on rather than whether they know Next.js.
The split most teams end up with
Marketing site and public content on Next.js, product application in plain React. That split is common because the two jobs have different requirements and different deployment risk. It also means you may want two different people, or one person who has genuinely done both rather than one who has done App Router tutorials. If your work sits mostly on the framework side, our page on how to hire Next.js developers in India covers what changes about the screening.
Four React Situations We See, and the Hire Each One Points To
Each is a composite drawn from recurring patterns rather than an account of one client. If one of them describes your situation, the hire it points to is usually the right one.
The dashboard that got slow and nobody knows when
A four-year-old application, originally scaffolded with Create React App, now with a data grid of a few thousand rows, a filter bar and a set of charts. Typing in the filter feels laggy, and the team has already added useMemo in a dozen places without improvement. Field reports say it is worst on mid-range Windows laptops.
What is usually happening: the filter input is controlled state held in a component that also owns the grid, so every keystroke re-renders the whole page, and the grid is not virtualised. The fix is to move the input state into the input's own component, pass the committed value down, deferring it with useDeferredValue so the grid updates behind the typing rather than blocking it, and virtualise the rows. The hire is a senior React engineer who profiles first, and the engagement is short and measurable: an INP number before and after, taken from real users rather than a lab run.
Redux that grew into a second database
A B2B product with roughly thirty screens where nearly every API response is stored in Redux with a matching loading flag and error field. Data goes stale between screens, two components sometimes show different values for the same record, and a simple new endpoint takes a day of boilerplate.
The work here is a migration, not a rewrite. Server data moves to RTK Query or TanStack Query one domain at a time while the store keeps the genuinely client-side pieces. Each slice removed is a pull request that ships. The hire is someone who has done exactly this before and will insist on doing it incrementally, and the interview question that finds them is asking what they would move first and why. The right answer is usually the most-read, least-mutated domain, because it is the lowest risk and it proves the pattern to the rest of the team.
Three product teams and no shared components
Buttons exist in four versions across three repositories, none of the modals trap focus the same way, and a rebrand means touching everything. The company wants a design system.
This is not primarily a React problem, which is why it gets staffed wrong. It needs someone who can design a component API that survives contact with three teams' requirements, type it properly in TypeScript, get the accessibility right at the primitive level, and set up versioning, documentation and a migration path so adoption is not a mandate nobody follows. Storybook is the visible artefact; the real deliverable is the API and the release discipline. Hire senior, expect the first six weeks to produce very few components, and judge the work by how few exceptions the consuming teams have to ask for.
A founding engineer for a product with no code yet
Pre-launch, one designer, a rough spec, and a need to be in front of users quickly. The temptation is to hire the most credentialled React engineer available. The better fit is someone with product instinct who will argue about scope, choose boring technology, and ship something users can break.
What matters at this stage: comfort making decisions with incomplete information, willingness to use an off-the-shelf component library instead of building one, and the judgement to leave the state management simple until the shape of the product is known. Ask them what they would deliberately not build in the first month. A candidate with a long list is worth more here than one with a long CV.
Working With React Engineers in India: the Honest Version
The timezone question deserves arithmetic rather than reassurance, so here is the arithmetic.
The overlap window, calculated
India sits five and a half hours ahead of UTC all year, with no clock change in either direction, so the offset you plan around in January is the one you get in July. Take an engineer working 09:30 to 18:30 in Mumbai: in UTC that is 04:00 until 13:00. Everything below is arithmetic on those two numbers, and you can redo it yourself.
London. On GMT, a 09:00 to 17:00 day is 09:00 to 17:00 UTC, so you overlap from 09:00 to 13:00 UTC: four hours, your whole morning. On British Summer Time the London day is 08:00 to 16:00 UTC and the overlap becomes five hours. This is the easy case and it is why UK teams find India straightforward.
Sydney. On AEST, which is UTC+10, a 09:00 to 17:00 day ends at 07:00 UTC. The Indian day starts at 04:00 UTC, so you overlap from 04:00 to 07:00 UTC: three hours, which is your afternoon from 14:00 and their morning from 09:30. On AEDT the overlap shrinks to two hours. Auckland on NZST gets about one hour, and on NZDT effectively none.
US Eastern. On EST, which is UTC-5, your 09:00 start is 14:00 UTC. The Indian day already ended at 13:00 UTC. Overlap is zero. On EDT your 09:00 is 13:00 UTC, which is the exact minute the Indian day ends, so it is zero in practice too.
US Pacific. On PST your 09:00 is 17:00 UTC, four hours after the Indian day finished. Zero, and not close.
So if you are on the US East or West Coast, a standard Indian working day gives you nothing at all, and any page that tells you otherwise is not doing the sums. Real overlap comes from shifting the Indian day, which is a decision with a human cost that should be made openly. A 13:30 to 22:30 IST shift is 08:00 to 17:00 UTC and gives US Eastern three hours, from 09:00 to 12:00 Eastern, ending at 22:30 in India. Reaching Pacific hours at all means working past 22:30 IST for a window of roughly ninety minutes at the start of the Pacific morning. That is a genuine imposition on someone's evening. It narrows the pool of engineers willing to take the role and it shortens how long they are happy in it, so agree the hours explicitly with the engineer and with us before the engagement starts rather than discovering them in month two.
What the gap is actually good for
The half-open overlap is not only a cost. Frontend work has a natural rhythm that suits it: you review pull requests and leave design feedback at the start of your day, which is the end of theirs, and the work continues while you sleep. Reviews stop being an interruption and become a scheduled activity. Bugs found in your afternoon are often fixed before your morning.
What breaks in that model is anything needing a conversation. Ambiguous tickets, design questions with no obvious answer, an incident. Those need the overlap window, which is why the window should be protected for exactly that and not filled with status meetings.
Working written-first
Distributed React work runs on artefacts rather than conversations. Tickets that contain the acceptance criteria and the edge cases, not a title. Pull requests with a description of what changed and why, screenshots or a short recording of the interaction, and a note on what was not done. Design handoff through Figma with states specified, including empty, loading, error and the long-string case, because the questions an engineer would otherwise ask in a hallway cost a day when asked across a timezone.
Standups written rather than spoken work better than the alternative here. So does a decision log, even a rough one, because six months later the reason a context was split matters more than the commit that did it.
Code review, quality and how you keep control
The honest answer to "will I lose control of quality" is that you keep it through the same mechanism you would use for a local hire: your repository, your branch protection, your review standard, your definition of done. An engineer working from India should be raising pull requests into your main repository, running your CI, and getting the same comments a colleague sitting next to you would get. If a supplier proposes shipping you finished work from a repository you cannot see, that is the part to refuse.
Practical gates that travel well: lint and type checks in CI so review is about design rather than formatting, a bundle-size check that fails loudly, a test that covers the flow that broke last time, and a Lighthouse or field-data check on the routes that matter commercially. On the interview side, we assess written English properly, because in this working model most communication is written and a candidate who is fluent in a call but unclear in a pull request description will cost you time every day.
Code ownership, access and data
Ownership of the code and any intellectual property created is settled in the agreement you sign before work starts, along with confidentiality and data handling terms. Read those clauses with your own counsel rather than taking a summary from a vendor page, including this one. If you process personal data of people in the EU or UK, the transfer arrangements are a question for your legal advisers, and you should expect a straight answer about where data is stored and who can access it before anyone gets a repository invitation.
On access, the practical baseline is the same as for any remote contributor: named accounts rather than shared ones, single sign-on where you have it, permissions scoped to what the person needs, no production database access for frontend work, and a defined offboarding process. This page makes no security certification claims. Where your procurement checklist asks for evidence against a named standard, put that question to us in writing and take a plain yes or no.
The costs people forget to budget
Onboarding is real work regardless of where the engineer sits, and on a mature React codebase it is a few weeks before the pace is normal. Someone on your side has to answer questions, and that person is usually your best engineer. Documentation that was tolerable when everyone was in one room becomes the bottleneck. Add the coordination overhead of a partial overlap and the fact that a question asked at the wrong hour costs a day. None of this is an argument against hiring in India; it is an argument for staffing the onboarding rather than assuming it away.
Where React Hires Go Wrong
Hiring a title instead of a skill. "Senior React developer" tells you nothing about whether the person can design state for your product. Write the brief around the problem: the codebase's age, the framework, the state library, the thing that is currently painful. Candidates self-select accurately against a specific brief and badly against a generic one.
Assuming React covers the whole browser layer. It does not cover design, it does not cover CSS architecture at scale, and it does not cover the backend. If your API is also being built, you need someone on that side; see our pages for teams that hire Node.js developers in India when the API is JavaScript too.
Testing with a puzzle instead of the job. Algorithm rounds select for interview practice, not for the ability to read a 200-file component tree. A better test is a small, real task in a codebase resembling yours, timeboxed and paid, with a conversation about the trade-offs afterwards.
Skipping the code review question. How someone gives and receives review predicts more about a distributed engagement than their technical ceiling does. Ask for an example of a review comment they disagreed with and what happened next.
Letting the first month have no visible output. Set something shippable in the first two weeks, however small, so both sides find out early whether the working model functions. Discovering a mismatch in week two is a conversation; discovering it in month three is a project. Say so in week two rather than month three, and a different React engineer reaches you within 48 hours, drawn from a bench of candidates instead of the sole name you are stuck deciding on again.
Underestimating the knowledge that leaves. Whoever holds the model of why your component tree looks the way it does is holding something expensive. Written decisions, a maintained README and pairing on the parts only one person understands are what stop that becoming a problem later.
The React Stack Our Engineers Work In
Tell us which of these your codebase actually uses and which you are trying to move away from. The second list is usually the more useful one.
How to Hire React Developers in India With Us
Hiring a React engineer directly in India means sourcing, screening, an offer, and then waiting out the notice the candidate owes their current employer, which in that market is rarely short. It is why someone you interview in March can realistically start in June. Because our React engineers are already on the bench and not being recruited once your brief lands, that wait disappears: matching from your brief to a shortlist runs in 48 hours, and a chosen engineer can be working on your codebase within 7 days.
Describe the codebase, not the role
React version, state library, whether you server-render, test framework, team size, and the thing that is currently painful. That paragraph does more for matching than a job specification.
We shortlist against it in 48 hours
You get profiles with the specific React experience you asked for, plus what they have not done, because a mismatch you find in week one is cheaper than one you find later.
You run your own technical interview
Use the questions above or your own. Pair on a real ticket if you prefer. We do not gate you from the engineer or sit in the conversation for you.
Agree the working model before day one
Overlap hours, standup format, review standard, what ships in the first fortnight. Settling this in advance is what makes the timezone gap a schedule rather than a surprise.
Ways to Structure a React Engagement
A defined piece of work
A rendering performance pass with a measured before and after. A Redux to query-cache migration. A component library extraction. Work with an edge you can see, run as a scoped engagement.
A dedicated React engineer
One engineer inside your team, your repository, your board, your review standard, working your agreed overlap. The usual shape for ongoing product development and the one most people mean by hiring a dedicated React developer.
A frontend squad
Several engineers with a lead who owns the architecture, plus QA where the surface needs it. Sensible when the frontend is a product in its own right rather than a layer on someone else's roadmap.
Commercial terms, working hours and contract shape are agreed with you in writing before anyone starts, and we would rather have that conversation against your actual brief than publish numbers that would not apply to it. If React is one part of a wider need, start from hiring developers in India and we will work backwards from the product.
Frequently Asked Questions
Should I ask for a React developer or a React Redux developer?
Ask for a React developer and screen for state management. Redux is a library, not a discipline, and someone fluent in Redux Toolkit will pick up Zustand or TanStack Query in a weekend. If your codebase already runs on Redux, say which Redux: a store written in 2018 with action constants and sagas is a different reading job from a modern configureStore setup.
We inherited a Redux codebase and nobody here wrote it. Who should we hire?
Someone whose strongest skill is reading rather than building. The work in an inherited store is reconstructing why the shape is what it is, then removing what no longer earns its place. Ask candidates about the largest store they have maintained and what they took out of it, not what they added. A developer who only describes features they shipped has not done this particular job.
What usually turns out to be wrong with a Redux store that has been running for years?
Derived values stored next to the data they came from, a state tree shaped like whatever the API happened to return, business rules that drifted into middleware, and a persistence layer rehydrating a shape the reducers no longer expect. The last one is the nastiest, because it only affects returning users and the bug report reads that the app is broken for some people and fine for everyone else.
What is the difference between a React developer and a frontend developer?
Overlap, but not equivalence. A frontend developer owns the browser layer generally: markup, CSS, layout, cross-browser behaviour. A React engineer owns component boundaries, state ownership, render behaviour and data flow, and is judged on whether the application stays changeable at fifty screens. Plenty of strong CSS people write React that re-renders the world on every keystroke, and plenty of strong React people write weak CSS.
How do I tell a developer who has shipped React from one who followed tutorials?
Ask about failures rather than features. A stale closure inside setInterval, a list that kept the wrong row expanded after a sort, a hydration mismatch that only appeared in production, an effect that fetched twice under StrictMode. People who have shipped tell these stories immediately and with irritation. People who have not describe the hooks API back to you.
Do I need TypeScript in the job description?
If your codebase is already TypeScript, yes, and screen for it properly rather than accepting it as a listed skill. The gap that matters is between someone who types props and someone who can type a generic component, a discriminated union of states, and the return of a custom hook. If you are on plain JavaScript, hiring a TypeScript-strong engineer is still the cheaper path when you eventually migrate.
Can the same person cover React and Next.js?
Often, but not automatically. Next.js adds a server runtime, a routing convention, a caching model and the server component boundary, and none of that is learned by writing components. A React engineer moving to the App Router for the first time will be productive quickly and will also make the classic mistakes, usually around what can cross the client boundary and what gets cached.
What working overlap can I realistically expect with a team in India?
Do the sum in UTC. A Mumbai day of 09:30 to 18:30 lands at 04:00 to 13:00 UTC, since India runs five and a half hours ahead with no clock change all year. London gets four hours of that in winter and five in summer, Sydney around three, New York and San Francisco none at all. Overlap with North America has to be bought with a shifted Indian day, agreed before anyone starts.
Can I hire a dedicated React developer instead of a project team?
Yes, and for most product work it is the better shape. A dedicated engineer sits in your repository, your tracker and your standup, and is measured by the same review standard as everyone else on the team. Project-shaped delivery suits work with a defined edge, such as a component library extraction or a rendering performance pass on an existing app.
How quickly can a React developer actually start?
Matching from your brief to a shortlist takes 48 hours, and a chosen engineer can be on your codebase within 7 days. It works because the React engineers are already with us, sitting on the bench before your brief arrives. Hiring directly in India is slower for a structural reason: the candidate owes notice to their current employer, so an interview in March often becomes a start in June.