Curated interview practice questions with answers. These are practice scenarios, not a verified list of past interview questions.
About Thoughtworks hiring for React JS roles
Thoughtworks is a global technology consultancy known for agile software delivery, continuous delivery and its Technology Radar publication. It works on custom software, data platforms and digital transformation for enterprise clients. In India it hires for developers, quality analysts, data engineers and data scientists. Teams usually work closely with client engineers.
For React JS roles, this Thoughtworks practice set focuses most on State Management (6), Next.js and Advanced React (5), Routing and Forms (4), React Hooks (4). It has 5 easy, 23 medium, 2 hard questions, so you can start easy and work up to the harder ones.
Company type
Consulting
Headquarters
Chicago, Illinois, USA
Main India offices
Pune, Bengaluru, Chennai, Gurugram, Hyderabad
Thoughtworks React JS interview process
Online coding assessment
Code pairing round
Technical interview
Cultural fit or social change round
Leadership round
Typical pattern based on public candidate experiences. Rounds vary by role, team and year.
Solved for ThoughtworksStart 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
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.
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.
Middleware sits between dispatching an action and the reducer, letting you intercept actions for side effects. Signature: store => next => action => {...}. Common uses are async logic (redux-thunk, included by default in Redux Toolkit), logging, analytics, error reporting and the RTK Query cache middleware. Redux Toolkit also provides listenerMiddleware for reacting to actions, a lighter alternative to redux-saga for most cases.
05
How do you read and update query parameters like ?page=2&sort=price?
Use useSearchParams, which works like useState for the query string.
import { useSearchParams } from 'react-router';
function ProductList() {
const [params, setParams] = useSearchParams();
const page = Number(params.get('page') ?? 1);
const sort = params.get('sort') ?? 'popular';
const next = () => setParams({ page: String(page + 1), sort });
return <Pagination page={page} onNext={next} />;
}
Keeping filters in the URL makes them shareable and bookmarkable.
06
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.
07
Where should you store the logged-in user's auth token in a React app?
The safest common choice is an httpOnly, Secure, SameSite cookie set by the server, because JavaScript cannot read it, which protects it from XSS theft. Keep only non-sensitive user info, such as name and role, in React state or context. If you must use tokens in JavaScript, keep the access token in memory, use short expiry and refresh tokens via cookies. Avoid localStorage for tokens.
08
How would you explain to a non-technical manager why our marketing pages need server rendering?
I would keep it simple: a pure client-side React page sends an almost empty HTML file, so some crawlers and social previews see little content and users on slow phones see a blank screen longer. Server rendering sends ready HTML, improving SEO and first load. I would back this with a Lighthouse comparison and search console data, and suggest a framework like Next.js only for pages that need it.
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}.
10
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.
11
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.
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.
13
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.
Use an i18n library such as react-i18next or, in Next.js, next-intl. Store translations in JSON files per locale, reference keys like t('cart.title') instead of hard-coded text, and handle plurals, dates, numbers and currency with Intl APIs. Put the locale in the URL, like /hi/products, for SEO and shareable links. For Indian audiences, check fonts for Devanagari and other scripts and test longer translated text.
Situation: our app ran on an unmaintained Create React App setup with slow builds. Task: move to Vite without stopping feature work. Action: I wrote a migration plan, fixed incompatible imports and env variables in a branch, ran both builds in CI for a week, and trained the team on differences. Result: we switched over a weekend, local start time went from over a minute to a few seconds, and nothing broke for users.
17
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.
fireEvent dispatches a single DOM event, such as one change event. user-event simulates full user interactions: typing fires keydown, keypress, input and keyup for every character, clicking includes pointer and focus events, and it respects disabled elements and visibility. This finds bugs that fireEvent misses. In current versions, call userEvent.setup() and await each interaction because they are asynchronous.
19
What are nested routes and what is the role of Outlet?
Nested routes let a parent route render a shared layout, like a dashboard sidebar, while child routes render inside it. The parent component places <Outlet /> where the matching child should appear. For example, /dashboard renders DashboardLayout, and /dashboard/orders renders Orders inside its Outlet. This keeps layouts consistent, avoids repeating headers and lets each section load its own data.
20
React changes fast. How do you keep your skills current?
I follow the official react.dev blog and docs, read release notes for React, Next.js and the libraries we use, and try new features in a small side project before using them at work. For example, when React 19 introduced Actions and useOptimistic, I rebuilt a form in my practice app first, noted pitfalls, and then shared a short demo with my team before we adopted it.
21
A developer stores fullName in state and updates it in a useEffect whenever firstName or lastName changes. What would you suggest?
This is redundant derived state. It causes an extra render and risks the values going out of sync. Compute it during render instead: const fullName = firstName + ' ' + lastName. If the calculation is expensive, wrap it in useMemo. As a rule, if a value can be calculated from existing props or state, do not store it in state and do not sync it with an effect.
Hydration is the process where React, running in the browser, attaches event handlers and state to HTML that was already rendered on the server, making it interactive. React expects the first client render to match the server HTML exactly; if not, it reports a hydration mismatch. Until hydration finishes, the page is visible but buttons may not respond, which is why reducing client JavaScript matters.
23
How do you set up a Redux store and use it in components?
Disabling it usually hides a stale closure bug. The rule tells you the effect reads a value that can change. Instead, include the dependency, move a function inside the effect, use the updater form of setState so state is not needed, or move non-reactive logic into useEffectEvent. If an object dependency changes every render, create it inside the effect or memoise it. Suppress only with a clear comment.
25
A teammate writes setCount(count + 1) three times in a click handler and is surprised that the count increases by only one. Explain why.
Inside one render, count is a constant snapshot, say 0. Each call schedules setCount(0 + 1), so all three set the same value 1, and React batches them into one render. State does not change immediately after calling the setter. To increment three times, use the updater form setCount(c => c + 1), which queues functions that each receive the latest pending value.
26
An orders table renders 10,000 rows and the page freezes on load and scroll. What would you do?
First question whether users need all rows at once: server-side pagination or infinite scroll with cursor-based loading may solve it. If a long scrollable list is required, virtualise it with TanStack Virtual so only around 30 rows exist in the DOM. Also memoise row components, avoid heavy formatting in render by precomputing, and move sorting or filtering off the main thread if it is expensive.
27
What is the difference between controlled and uncontrolled components?
In a controlled component, the form value lives in React state and the input gets value and onChange props, so React is the single source of truth. In an uncontrolled component the DOM keeps the value and you read it with a ref or FormData when needed. Controlled inputs make validation and conditional UI easy; uncontrolled inputs are simpler and can perform better for large forms.
28
What do useActionState and useFormStatus do in React 19?
useActionState wraps an action function and returns [state, formAction, isPending]; you pass formAction to a form's action prop and the returned state holds the result, like a validation error. useFormStatus, from react-dom, lets a child component such as a submit button read the pending status of the parent form without prop drilling. Together they remove a lot of manual loading and error state code.
29
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.
30
What is atomic state management, as in Jotai or Recoil-style libraries?
Atomic state splits state into small independent units called atoms. Components subscribe to only the atoms they use, and derived atoms compute values from others, similar to a spreadsheet. This gives fine-grained re-renders without selectors or a big central store. Jotai is the popular option today; Recoil is no longer maintained. It suits apps with many independent pieces of interactive state.
Tips to crack the Thoughtworks React JS interview
Practise pair programming with test-driven development, since Thoughtworks interviews often include coding together with an interviewer.
Read the latest Thoughtworks Technology Radar and form opinions on a few tools or techniques it lists.
Prepare to discuss social and economic justice values, which Thoughtworks openly includes in its culture discussions.
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; Thoughtworks interviewers usually ask follow-ups on your first answer.
Frequently asked questions
How many rounds are there in the Thoughtworks React JS interview?
Candidates usually go through 5 stages: Online coding assessment; Code pairing round; Technical interview; Cultural fit or social change round; Leadership 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 Thoughtworks React JS interview?
This practice set leans on State Management (6), Next.js and Advanced React (5), Routing and Forms (4), React Hooks (4). Revise those first, then practise explaining one or two of your own projects end to end, because most Thoughtworks interviewers ask you to walk through real work.
Are these the exact questions asked at Thoughtworks?
No. These are curated practice questions that match the skills and difficulty usually tested in consulting interviews like Thoughtworks's. They are not a leaked or verified list of past questions.
Where does Thoughtworks hire React JS professionals in India?
Thoughtworks has large teams in Pune, Bengaluru, Chennai, Gurugram, Hyderabad. Openings and locations change often, so check the Thoughtworks careers page and filter by city and experience.