
You're probably here because you have a senior React role to fill and you want to get the hire right.
The hard part, especially if React isn't your area, is knowing what to actually ask. Most question lists you'll find online are beginner stuff. They're fine for screening junior developers, but they won't do much when you want to hire a senior React developer. A candidate can ace every one of them, sound confident, use the right words, and still not be the person you need.
And even when you do ask the right question, how do you know if the answer is solid or just well-rehearsed? Without a strong React background, it's hard to tell the difference between someone who really knows their stuff and someone who's good with words. By the time that becomes obvious, you're already two months in with the wrong dev.
So we’ve provided a list of real senior-level interview questions to close that gap. Use it in your interviews to spot a good candidate. And the fun part is, you don't need to be a React expert to use it.
The questions are grouped by topic so you can pull from each section and build a focused 60 to 90 minute interview without scrambling or doubling up on the same concept.
For each question, you'll get the ideal answer, what a senior engineer sounds like versus a mid-level one, and red flags to watch for.
If you're a candidate who landed here, don't memorize the answers. Focus on the trade-offs behind each one. That's what senior-level conversations sound like.
One thing to keep in mind: seniority doesn't mean knowing more APIs. It means reasoning clearly about trade-offs, constraints, and scale.
Most candidates who've worked with React for a few years can define things. That's not what you’re looking for. What you're trying to find out is whether they understand why React works the way it does, and what happens when those internals work against them.
What it tests: Whether the candidate understands how React decides what to update, not just that it uses a virtual DOM.
Ideal answer: React builds a virtual DOM tree and diffs it against the previous one on each render. It uses a heuristic algorithm that assumes components at the same tree position are the same type, and that keys uniquely identify list items. It breaks down when keys are unstable, like using array indexes, or when the tree structure changes in ways React doesn't expect, causing unnecessary unmounts and remounts.
Senior vs mid-level: A mid-level candidate explains what the virtual DOM is. A senior explains where the diffing algorithm makes assumptions and how those assumptions can hurt performance or cause bugs.
Red flags: Candidate describes reconciliation as "React updates only what changed" without explaining how it decides what changed.
What it tests: Whether the candidate thinks beyond basic form handling to performance and architecture implications.
Ideal answer: Controlled components store form state in React, giving you full control but triggering re-renders on every keystroke. Uncontrolled components let the DOM manage state via refs, which is simpler but harder to validate or sync. At scale, the choice matters when you have large forms with many fields, where controlled components can cause performance issues if not managed carefully with techniques like memoization or form libraries like React Hook Form.
Senior vs mid-level: A mid-level candidate explains the definition. A senior talks about the performance trade-offs and when they'd reach for a form library instead.
Red flags: Candidate says one is always better than the other without any context.
What it tests: Whether the candidate understands how keys affect reconciliation, not just that React requires them.
Ideal answer: Keys tell React which items in a list are the same between renders, so it can reuse existing DOM nodes instead of rebuilding them. Using unstable keys like array indexes means React may reuse the wrong node, leading to state bugs or incorrect UI, especially in lists that can reorder or filter. A stable, unique key tied to the data is what makes reconciliation predictable.
Senior vs mid-level: A mid-level candidate knows keys prevent warnings. A senior explains how wrong keys cause subtle state bugs and can silently break list behavior.
Red flags: Candidate says index keys are fine as long as the list doesn't change, without acknowledging edge cases around filtering or sorting.
What it tests: Whether the candidate understands React's design philosophy and can reason about when patterns break down.
Ideal answer: React is built around composition. You share behavior by passing components as props or wrapping them, not by extending base classes. Inheritance creates tight coupling and is hard to follow across a large codebase. In practice, composition handles almost everything, but candidates who've worked at scale may have hit cases where patterns like render props or HOCs introduced their own complexity.
Senior vs mid-level: A mid-level candidate explains what composition is. A senior has an opinion on when composition patterns themselves become a problem and what they did about it.
Red flags: Candidate hasn't thought about this beyond the textbook answer or can't give a real example.
What it tests: Whether the candidate understands how React abstracts browser events and where that abstraction leaks.
Ideal answer: React wraps native browser events in a synthetic event object to normalize behavior across browsers. In older versions, events were pooled and reused, meaning you couldn't access them asynchronously without calling event.persist(). React 17 moved event delegation from the document to the root DOM node, which matters when embedding React in non-React apps. Most of the time it's invisible, but it surfaces in edge cases around third-party integrations and async handlers.
Senior vs mid-level: A mid-level candidate knows React uses synthetic events. A senior knows about event delegation changes in React 17 and can explain when the abstraction causes real problems.
Red flags: Candidate has never encountered a case where the event system caused an issue and can't reason about when it might.
What it tests: Whether the candidate can reason about migration risk, not just recite why hooks are better.
Ideal answer: You wouldn't rewrite everything at once. Class components and hooks coexist fine, so the approach is incremental, starting with new components using hooks and migrating existing ones when there's a clear reason, like simplifying lifecycle logic or sharing stateful behavior. The real risk is in components with complex lifecycle methods like componentDidUpdate with multiple conditions, where a naive migration to useEffect can introduce subtle bugs.
Senior vs mid-level: A mid-level candidate talks about why hooks are better. A senior talks about migration strategy, risk, and which components are actually dangerous to touch.
Red flags: Candidate says they'd rewrite it all or dismisses class components entirely without acknowledging the risk of touching stable code.
What it tests: Whether the candidate understands the limits of error boundaries, not just how to implement one.
Ideal answer: Error boundaries catch rendering errors in the component tree below them and let you show a fallback UI instead of crashing the whole app. They don't catch errors in event handlers, async code, or server-side rendering. Placement matters: one top-level boundary is a safety net, but you also want boundaries around isolated sections like dashboards or widgets so one failure doesn't take down the entire page.
Senior vs mid-level: A mid-level candidate knows how to write an error boundary. A senior thinks about placement strategy and knows exactly what they won't catch.
Red flags: Candidate doesn't know the limitations or thinks one global error boundary is sufficient.
What it tests: Whether the candidate has a clear mental model of what React expects to happen during rendering.
Ideal answer: The render phase should be pure. React may call it multiple times, especially in concurrent mode, so any function that runs during render needs to be side-effect free. Side effects belong in useEffect, event handlers, or outside the component entirely. Mixing them, like writing to a ref or making an API call during render, causes bugs that are hard to reproduce and harder to debug.
Senior vs mid-level: A mid-level candidate knows to put side effects in useEffect. A senior understands why render purity matters in concurrent mode and can give examples of bugs that come from violating it.
Red flags: Candidate isn't aware of concurrent mode or doesn't understand why render needs to be pure.
Defining state is easy. Knowing where to put it, when to lift it, and when to pull in a library is what actually matters at scale. A lot of candidates who look senior on paper start to show cracks here. The questions in this section will find those cracks.
What it tests: Whether the candidate has a principled decision framework or just reaches for Redux by default.
Ideal answer: Local state is for anything that only one component, or a small slice of the tree, cares about. Global state is for data that multiple unrelated parts of the app need to read or write. The mistake most teams make is globalizing too early, which creates unnecessary complexity. A good rule of thumb is to start local and only lift or globalize when you have a concrete reason to.
Senior vs mid-level: A mid-level candidate knows the difference. A senior has a framework for deciding and can talk about cases where they got it wrong and had to refactor.
Red flags: Candidate defaults to global state for everything or can't articulate when local state is enough.
What it tests: Whether the candidate understands Context's performance limitations and knows when to reach for something else.
Ideal answer: Context re-renders every consumer when its value changes, even if the component only cares about part of that value. This becomes a real problem in large apps with frequently changing state. The fixes are splitting contexts by concern, memoizing values, or replacing Context with a proper state manager for high-frequency updates. Context works well for slow-moving data like themes or auth state, not for things that change constantly.
Senior vs mid-level: A mid-level candidate knows Context exists and how to use it. A senior knows exactly when it hurts performance and has a strategy for dealing with it.
Red flags: Candidate thinks Context is a full Redux replacement without any caveats.
What it tests: Whether the candidate can reason about state complexity, not just recite when each hook is "supposed" to be used.
Ideal answer: useState is fine for simple, independent values. useReducer makes more sense when state transitions are complex, when the next state depends on the previous one in non-trivial ways, or when you want to centralize update logic for easier testing. In practice, a lot of teams overuse useReducer for simple cases, adding boilerplate without real benefit. The honest answer is it often comes down to team convention.
Senior vs mid-level: A mid-level candidate gives the textbook answer. A senior has a real opinion and can talk about cases where either choice caused problems.
Red flags: Candidate says useReducer is always better for complex state without any nuance.
What it tests: Whether the candidate understands that data from an API is fundamentally different from UI state and should be treated that way.
Ideal answer: Server state is async, needs to be fetched, cached, and kept in sync with the backend. Client state is synchronous UI state like modals, filters, or form inputs. Mixing them in the same store creates a mess. Libraries like React Query or SWR exist specifically to handle server state, including caching, background refetching, and loading states, so you don't have to reinvent that logic manually.
Senior vs mid-level: A mid-level candidate knows what React Query does. A senior understands the architectural reason it exists and has opinions on where the boundary between server and client state should sit.
Red flags: Candidate stores all API responses in Redux without questioning whether that's the right tool.
What it tests: Whether the candidate knows multiple solutions and can pick the right one based on context.
Ideal answer: The first move is composition, passing components as props instead of data through multiple layers. If that's not enough, Context works well for slow-moving shared data. For more complex cases, a state manager makes sense. The mistake is jumping straight to a global solution when restructuring the component tree would have solved it cleanly.
Senior vs mid-level: A mid-level candidate knows Context solves prop drilling. A senior reaches for composition first and can explain why that's usually the cleaner fix.
Red flags: Candidate's only answer is Context or Redux, with no mention of component composition.
What it tests: Whether the candidate has dealt with real async bugs and knows how to prevent them systematically.
Ideal answer: Race conditions happen when multiple async requests are in flight and the last one to resolve isn't always the most recent one. The fix is cancellation, either with AbortController for fetch requests or cleanup functions in useEffect to ignore stale responses. Libraries like React Query handle a lot of this automatically, which is one of the strongest arguments for using them over hand-rolled async logic.
Senior vs mid-level: A mid-level candidate knows to clean up in useEffect. A senior can describe a real race condition they encountered, how it manifested, and how they fixed it.
Red flags: Candidate hasn't thought about race conditions or thinks setting state in a finally block is sufficient protection.
Anyone can add useMemo and call it an optimization. A senior engineer knows what's actually causing the problem before touching anything. Most performance issues in React come down to unnecessary re-renders, and most unnecessary re-renders come down to not understanding how React decides to update. That's what this section tests.
What it tests: Whether the candidate has a complete mental model of React's rendering triggers, not just the obvious ones.
Ideal answer: A component re-renders when its state changes, its props change, its parent re-renders, or a context it consumes changes. The tricky part is that a parent re-render causes all children to re-render by default, even if their props didn't change. That's where most performance bugs hide. React.memo can prevent this, but only if the props pass a shallow equality check, which breaks down with objects and functions defined inline.
Senior vs mid-level: A mid-level candidate lists state and prop changes. A senior explains the parent re-render cascade and knows exactly where shallow equality breaks down.
Red flags: Candidate doesn't mention parent re-renders or thinks props have to change for a child to re-render.
What it tests: Whether the candidate understands that memoization has a cost and isn't a default optimization.
Ideal answer: Memoization adds overhead: React has to store the previous value and run a comparison on every render. If the computation is cheap or the dependency changes frequently, you're paying the cost without getting the benefit. useCallback is commonly overused, wrapping functions that get passed to components that aren't even memoized, which means the memo does nothing. The right time to reach for these is after you've confirmed there's a real performance problem, not as a precaution.
Senior vs mid-level: A mid-level candidate knows what these hooks do. A senior knows when they make things worse and has removed them from a codebase after profiling.
Red flags: Candidate wraps everything in useMemo by default or thinks it's always a safe optimization.
What it tests: Whether the candidate understands the order of execution in a functional component, especially around hooks and effects.
Ideal answer: On each render, React calls the function, runs through the hooks in order, and returns JSX. After the DOM updates, useLayoutEffect runs synchronously, then useEffect runs asynchronously. On unmount, cleanup functions from both run in reverse order. The key thing is that hooks depend on call order, which is why you can't put them inside conditionals. In concurrent mode, React may render a component multiple times before committing, so side effects in the render body can run more than expected.
Senior vs mid-level: A mid-level candidate knows the basics of useEffect timing. A senior understands the difference between useLayoutEffect and useEffect, and knows how concurrent mode changes the picture.
Red flags: Candidate isn't aware of useLayoutEffect or doesn't know that concurrent mode can cause multiple renders before a commit.
What it tests: Whether the candidate thinks about bundle size and load time as part of their architecture, not as an afterthought.
Ideal answer: The starting point is React.lazy and Suspense for route-level splitting, which keeps the initial bundle small by only loading what the user needs upfront. From there, you look at heavy components or third-party libraries that aren't needed immediately and defer those too. The mistake is splitting too aggressively, which can cause waterfall loading if chunks depend on each other. Tooling like webpack-bundle-analyzer or Vite's build output helps you find what's actually worth splitting.
Senior vs mid-level: A mid-level candidate knows React.lazy exists. A senior thinks about chunk strategy, loading waterfalls, and has used tooling to make data-driven decisions about what to split.
Red flags: Candidate only knows route-level splitting or hasn't thought about the trade-offs of over-splitting.
What it tests: Whether the candidate knows virtualization and can reason about when it's necessary versus overkill.
Ideal answer: Rendering thousands of DOM nodes at once kills performance. Virtualization fixes this by only rendering what's visible in the viewport, using libraries like react-window or react-virtual. The trade-off is added complexity and some limitations around dynamic row heights and scroll restoration. For shorter lists, say under a few hundred items, pagination or simple batching is often cleaner. The decision should be driven by actual performance data, not assumption.
Senior vs mid-level: A mid-level candidate knows virtualization exists. A senior knows the trade-offs, has implemented it, and can talk about edge cases like dynamic heights or maintaining scroll position.
Red flags: Candidate reaches for virtualization immediately regardless of list size, or hasn't thought about its limitations.
What it tests: Whether the candidate has a systematic process or just guesses and adds memoization.
Ideal answer: Start with the React DevTools Profiler to identify which components are re-rendering and how often. Then look at why, checking what's changing in props, state, or context. Chrome's Performance tab helps with longer frame times and layout thrashing. The mistake most engineers make is optimizing before profiling, which wastes time and sometimes makes things worse. A senior treats performance like a bug: reproduce it, measure it, fix the root cause, then verify the fix.
Senior vs mid-level: A mid-level candidate mentions React DevTools. A senior has a full diagnostic process and treats performance issues with the same rigor as functional bugs.
Red flags: Candidate's first move is adding memoization or splitting components without any profiling data.
A quick note before we continue.
These aren't questions we pulled from a list. They're variants of what ReactSquad actually uses to vet senior React engineers internally. If a candidate can't handle these satisfactorily, they don't pass our bar, full stop.
You can run this entire loop yourself. And if you have a strong tech lead who can evaluate the answers, that's a solid approach. But if you'd rather skip the process and hire a ready candidate that's what we do. Every engineer we place has been vetted against questions like these.
Book a call with us and get a match within 48 hours.
Technical knowledge gets you to mid-level. Architecture is what separates engineers who can build features from engineers who can build systems. At this level, there's rarely a right answer. What you're listening for is whether the candidate can reason through trade-offs, justify decisions, and recognize when a pattern that worked at one scale breaks down at another.
What it tests: Whether the candidate thinks about maintainability and team scale, not just file organization.
Ideal answer: The structure should follow how the team works, not a template from a blog post. A common approach is grouping by feature or domain, keeping everything related to a feature, components, hooks, state, tests, close together. Shared utilities and design system components live separately. The goal is that a new engineer can find things without a tour. What breaks down is a flat structure that made sense at 10 components and becomes unnavigable at 100.
Senior vs mid-level: A mid-level candidate describes a folder structure. A senior talks about how structure affects team velocity, onboarding time, and how it needs to evolve as the codebase grows.
Red flags: Candidate has one structure they use everywhere regardless of team size or project complexity.
What it tests: Whether the candidate understands the real-world impact of architectural decisions on team productivity.
Ideal answer: Folder-based architecture groups files by type, components here, hooks there, utils somewhere else. It's simple and familiar but falls apart in large codebases because related code is scattered. Feature-based architecture groups everything by domain, so all the code for a checkout flow lives together. It's harder to set up but scales much better. The switch usually becomes necessary around the time engineers start spending more time finding files than writing code.
Senior vs mid-level: A mid-level candidate knows both patterns. A senior has lived through the pain of the wrong one and can describe exactly when and why they made the switch.
Red flags: Candidate prefers one without being able to articulate the trade-offs or hasn't worked on a codebase large enough for it to matter.
What it tests: Whether the candidate has a principled approach or just reaches for Redux on every project.
Ideal answer: The trigger is usually one of three things: state that needs to be shared across many unrelated components, complex state transitions that are hard to manage with hooks alone, or the need for strong developer tooling like time-travel debugging. Before reaching for a library, it's worth checking if Context plus useReducer handles it. If the app is mostly server state, React Query often removes the need for a global state manager entirely. The mistake is adding Redux to a project that didn't need it and spending weeks maintaining boilerplate.
Senior vs mid-level: A mid-level candidate knows the popular libraries. A senior can tell you the specific pain point that justifies each one and has probably made the mistake of adding one too early.
Red flags: Candidate adds a state library by default on every project or can't articulate what problem it's solving.
What it tests: Whether the candidate understands the performance and architectural implications of each rendering strategy, not just how to configure them.
Ideal answer: CSR works for apps where SEO doesn't matter and the user is already authenticated, like dashboards. SSR is the right call when you need fast first paint and good SEO, like marketing pages or e-commerce. Hybrid is where Next.js shines, letting you SSR the pages that need it and statically generate the ones that don't. The mistake is defaulting to SSR everywhere, which adds server load and complexity without always delivering a meaningful benefit to the user.
Senior vs mid-level: A mid-level candidate knows what SSR and CSR mean. A senior can walk through a real project and explain why they chose each strategy per route, and what they'd do differently now.
Red flags: Candidate defaults to one strategy for the whole app or can't explain the SEO and performance implications of each.
What it tests: Whether the candidate understands that reusability is a design problem, not just a code problem.
Ideal answer: The biggest mistake is building components that are too opinionated. A reusable component should handle the common case well and expose enough props or composition points to handle edge cases without requiring a rewrite. Documentation and discoverability matter as much as the code itself. If engineers don't know a component exists, they'll build their own. Tools like Storybook help, but the real driver is a team culture that reviews the component library before building something new.
Senior vs mid-level: A mid-level candidate talks about props and composition. A senior talks about adoption, documentation, and why most component libraries built internally never get used consistently.
Red flags: Candidate thinks reusability is purely a technical problem or hasn't thought about why engineers bypass shared components.
A candidate can be solid with React on the web and still struggle with React Native. The reasons are usually the same: they don't understand how the runtime actually works, they treat it like a browser, or they've never had to deal with platform-specific behavior under pressure. The questions in this section are designed to surface that quickly.
What it tests: Whether the candidate understands how React Native actually communicates with native code, not just that it does.
Ideal answer: The old Bridge serialized all communication between JavaScript and native as JSON, passing messages asynchronously across a queue. This created bottlenecks, especially for animations and gestures that needed frequent updates. JSI, the JavaScript Interface, replaces this with a direct reference to native objects from JavaScript, removing the serialization overhead and allowing synchronous calls. The new architecture built around JSI, Fabric and TurboModules, is what makes React Native performant enough for more demanding use cases.
Senior vs mid-level: A mid-level candidate knows React Native uses a bridge. A senior understands why JSI exists, what problems it solves, and how it changes the performance ceiling.
Red flags: Candidate hasn't heard of JSI or thinks the bridge is still the current standard without knowing the new architecture exists.
What it tests: Whether the candidate understands the platform-specific constraints of React Native beyond generic React performance advice.
Ideal answer: On the web, the main bottleneck is usually DOM updates and JavaScript execution on the main thread. In React Native, the bigger concerns are the JavaScript thread getting blocked, dropping frames on animations because of bridge overhead, and slow list rendering on lower-end Android devices. The JS thread and the UI thread are separate, so heavy computation in JavaScript can cause visible junk even if the UI itself is simple. Tools like the Hermes engine and libraries like Reanimated, which runs animations on the UI thread directly, exist specifically because of these constraints.
Senior vs mid-level: A mid-level candidate knows React Native has performance considerations. A senior can name specific bottlenecks, explain why they exist at the architecture level, and talk about tools they've used to fix them.
Red flags: Candidate gives generic React performance advice without addressing anything specific to the native runtime.
What it tests: Whether the candidate has worked beyond the JavaScript layer and understands when and how to reach into native code.
Ideal answer: Native modules are the bridge between JavaScript and platform APIs that React Native doesn't expose out of the box. The old approach used the Bridge with separate implementations for iOS and Android. With the new architecture, TurboModules load lazily and communicate via JSI, which is faster and more predictable. In practice, most teams use community libraries before writing their own. When you do write one, the key challenge is keeping the API consistent across platforms while handling the real differences in how iOS and Android expose the underlying functionality.
Senior vs mid-level: A mid-level candidate knows native modules exist. A senior has written one, understands the platform differences, and knows when TurboModules are worth the added complexity.
Red flags: Candidate has never needed to go beyond JavaScript or doesn't know how native modules fit into the new architecture.
What it tests: Whether the candidate understands the unique constraints of mobile navigation and can make principled decisions about structure.
Ideal answer: React Navigation is the standard, but the architecture decisions around it matter more than the library itself. Deep linking, auth flows, and nested navigators all need to be planned upfront because retrofitting them into an existing structure is painful. The common mistake is treating navigation as an afterthought and ending up with deeply nested navigators that are hard to reason about. On the performance side, heavy screens should be unmounted when not in focus rather than just hidden, and shared elements need careful handling to avoid jank during transitions.
Senior vs mid-level: A mid-level candidate knows React Navigation. A senior has designed a navigation architecture from scratch, dealt with deep linking and auth flows, and can talk about where it got complicated.
Red flags: Candidate only knows the basics of React Navigation and hasn't thought about auth flows, deep linking, or performance during transitions.
What it tests: Whether the candidate has dealt with the real complexity of building apps that work reliably without a network connection.
Ideal answer: Offline support requires thinking about three things: detecting connectivity, persisting data locally, and syncing changes when the connection returns. Libraries like WatermelonDB or MMKV handle local storage well. The hard part is conflict resolution, what happens when the user makes changes offline and the server has also changed in the meantime. Most teams underestimate this until they're deep into it. A senior engineer designs the sync strategy upfront rather than bolting it on later.
Senior vs mid-level: A mid-level candidate knows you can detect network status with NetInfo. A senior has built an actual offline-first feature, dealt with sync conflicts, and can talk about the architectural decisions that made it manageable.
Red flags: Candidate thinks offline support is just caching API responses or hasn't thought about what happens when syncing creates conflicts.
What it tests: Whether the candidate has a systematic debugging process specific to React Native, not just generic JavaScript debugging instincts.
Ideal answer: Start with Flipper or the React Native DevTools to get a baseline on what's happening. The React DevTools profiler shows component re-renders, and the Performance monitor in the dev menu shows JS and UI thread frame rates. If the JS thread is dropping frames, the issue is usually heavy computation or too many re-renders. If the UI thread is struggling, it's often animation-related, and Reanimated is usually the fix. For Android specifically, lower-end device testing is non-negotiable because issues that don't show up on a flagship will absolutely show up in production.
Senior vs mid-level: A mid-level candidate mentions Flipper. A senior has a structured process, knows which thread to look at first based on the symptom, and has debugged issues on real low-end devices.
Red flags: Candidate only uses console.log for debugging or hasn't tested on a range of devices.
Technical skill gets someone through the earlier sections. This tests something harder to screen for: whether the candidate actually takes responsibility for what they build. A lot of engineers are great at executing clear tasks and struggle the moment things get ambiguous. At the senior level, ambiguity is the job. The questions here are designed to find out if they can handle it.
What it tests: Whether the candidate takes ownership of clarity or waits for someone else to provide it.
Ideal answer: The first move is figuring out what's actually unclear and why. Sometimes requirements are vague because the problem itself isn't well understood yet, and the right answer is to push back and get alignment before writing a line of code. Other times, enough is known to start, and the gaps can be filled in as things take shape. A senior engineer knows the difference and doesn't use vagueness as an excuse to either block progress or build the wrong thing confidently.
Senior vs mid-level: A mid-level candidate asks for clarification and waits. A senior drives toward clarity, asks the right questions, and can make reasonable calls independently when waiting isn't an option.
Red flags: Candidate either builds without questioning anything or blocks completely until every detail is specified.
What it tests: Whether the candidate can collaborate across disciplines without either rolling over or creating friction.
Ideal answer: Disagreement is fine. How you handle it matters. The approach is to raise concerns early, with context, not complaints. If a design decision has performance implications or a product requirement adds significant complexity, that needs to be on the table before work starts, not after. A senior engineer respects that designers and PMs have context they don't always have, but also advocates clearly when something is going to cause a real problem. Once a decision is made, they commit to it.
Senior vs mid-level: A mid-level candidate goes along with decisions to avoid conflict. A senior raises concerns early, communicates the trade-offs clearly, and moves forward once a call is made.
Red flags: Candidate either never pushes back or frames every disagreement as a technical constraint that overrides product decisions.
What it tests: Whether the candidate uses code review as a quality gate or as a learning and alignment tool.
Ideal answer: Correctness first, but that's the floor. Beyond that, a senior engineer looks at whether the code is going to be maintainable six months from now by someone who didn't write it. That means naming, structure, edge cases that weren't handled, and patterns that are going to cause problems at scale. The tone matters too. A code review that makes junior engineers feel stupid is a failure regardless of how technically correct the feedback is.
Senior vs mid-level: A mid-level candidate checks for bugs and style. A senior looks at long-term maintainability, gives feedback that helps the other person grow, and understands that review is also a way to spread knowledge across the team.
Red flags: Candidate treats code review as gatekeeping, focuses only on style, or can't talk about how they communicate feedback to more junior engineers.
What it tests: Whether the candidate takes ownership under pressure and thinks systematically, not reactively.
Ideal answer: The priority order is: stop the bleeding, understand what happened, fix it properly. A senior engineer doesn't jump straight to a fix without understanding the scope of the problem first. They communicate clearly while the incident is active, loop in the right people without creating noise, and follow up with a postmortem that focuses on the system failure, not blame. The goal of the postmortem isn't to find who broke it. It's to find what made it possible to break.
Senior vs mid-level: A mid-level candidate talks about fixing the bug. A senior talks about the full incident lifecycle, communication during the outage, and what changed after to prevent recurrence.
Red flags: Candidate has never owned a production incident, focuses only on the technical fix, or can't talk about what happened after.
After doing enough of these interviews, patterns start to emerge. The strong candidates don't all have the same background or the same answers. But they have the same habits.
Having the questions is one thing. Running a loop that surfaces the right signal is another. Here's a structure you can use:
Interview 1 - Fundamentals + State Management: Pull from Sections 1 and 2. This is your baseline. You're checking if the candidate has a solid mental model of how React works before you get into anything complex. Expect this to run about 60 to 75 minutes with time for follow-up questions.
Interview 2 - Performance + Architecture: Pull from Sections 3 and 4. This is where the real separation happens. You're looking at how they think about scale, trade-offs, and decisions that affect more than just their own code. Give them a scenario if you can, something close to what your team actually deals with.
Interview 3 - React Native + Practical Deep Dive: Pull from Section 5 and the collaboration questions in Section 6. By this point you know if they can think. Now you're checking if they can own something. The collaboration questions here aren't soft skills filler, they tell you a lot about how someone will actually operate on your team.
Note: Don't grade on correctness. Grade on reasoning. A candidate who gives a slightly imperfect answer but walks you through their thinking clearly is more valuable than one who lands on the right answer but can't tell you how they got there. The first person will figure things out on your team. The second one will struggle the moment something doesn't match what they memorized.
Hiring a senior React engineer is hard, especially the critical part about interviews. If you ask the wrong questions, or are unsure about a good answer, you might be handing a confident mid-level candidate a senior offer.
If you've made it through this guide, you know what to ask, what a good answer sounds like, and what red flags to watch for.
But running a loop like this takes time. Three interviews, multiple reviewers, scoring, follow-ups, etc. That's before you factor in sourcing and scheduling. For most teams, it adds up to weeks, time you don’t really have enough of.
That's the problem ReactSquad was built to solve.
We have a less than 1% acceptance rate, rigorously vetting every candidate in our network to meet our quality bar.
We match you with a qualified senior React or React Native engineer within 48 hours, and every placement comes with a 14-day risk-free trial so you can be sure before you commit.
Skip the interview marathon and book a call with us today.