React Native Developer interview questions
100 real questions with model answers and explanations for React Native Developer candidates.
See a React Native Developer resume example →Practice with flashcards
Spaced repetition · Hunter Pass
Questions
I keep composition at the app layer, user flows in feature modules, business rules in domain code, and I/O behind data adapters.
- The app layer owns providers, navigation, startup, and environment wiring, but no feature rules.
- Each feature exposes screens and use cases through one public entry point instead of exporting its internals.
- Domain functions use plain TypeScript and know nothing about React Native, HTTP, SQLite, or TanStack Query.
- Data adapters map API and database records into domain types, which makes transport changes local.
Why interviewers ask this: The interviewer is checking whether the candidate can create practical layer boundaries without turning a medium-sized mobile app into an abstract framework.
I place state according to ownership: remote prices in a server-state cache, the cross-session preference in a small client store, and step-local fields near the form.
- TanStack Query owns prices, loading, errors, freshness, and refetching because the server remains authoritative.
- Zustand or Redux can persist the delivery preference when several screens need it across launches.
- The draft stays in a form controller or flow-scoped context and is discarded when checkout completes.
- I avoid copying query results into a global store because two writable copies drift during refetches.
Why interviewers ask this: A strong answer distinguishes ownership and lifetime instead of putting all three values into one global store.
I would keep the controlled TextInput value urgent and mark only the 5,000-row result update as non-urgent.
- With one query state, useDeferredValue(query) lets the input commit immediately while the list renders from deferredQuery and can show that its results are stale.
- If the input handler owns a separate filterQuery, I call setQuery(text) normally and wrap only setFilterQuery(text) in startTransition; the controlled input value must not be transitioned.
- I virtualize the result rows with FlatList or FlashList, and I split or move the 120 ms filter if it is one monolithic JavaScript task because a transition does not make that task cheap or interruptible.
- On a mid-range device in a release build, I measure key-to-paint p95, JavaScript stalls, result latency, and rendered rows against the 120 ms baseline.
Why interviewers ask this: The interviewer is checking whether the candidate protects input priority, chooses the right concurrent API, and verifies the result without treating transitions as a substitute for virtualization or CPU optimization.
I use key-value storage for small preferences, SQLite for the 10,000 queryable records, and Keychain or Keystore-backed storage for the token.
- MMKV gives fast synchronous reads for small hot values, but large synchronous serialization can still block the JS thread.
- AsyncStorage is adequate for non-sensitive JSON that is read asynchronously and does not need relational queries.
- SQLite supports indexes, transactions, pagination, and partial updates, which the offline record set needs.
- Tokens do not belong in MMKV or AsyncStorage because neither is a credential vault by default.
Why interviewers ask this: The question tests whether the candidate selects storage by data shape, access pattern, sensitivity, and thread cost.
I make the local database the UI source of truth and synchronize an explicit mutation outbox with the server.
- Every local edit and its outbox record commit in one SQLite transaction so a process kill cannot separate them.
- Sync uses stable client IDs, idempotency keys, a server cursor, and tombstones so retries and deletions are safe.
- Records carry server versions or update timestamps, and the product defines field-level merge or last-writer behavior for conflicts.
- The UI shows pending and conflicted states instead of pretending that an offline write is already confirmed remotely.
Why interviewers ask this: The interviewer is evaluating whether the design covers durability, retries, deletions, and conflicts rather than only caching reads.
I use hierarchical keys whose complete filter object represents the exact server result.
- A detail key can be orders, accountId, detail, orderId, while a list key includes accountId and a normalized filters object.
- Stable primitives and sorted filter values prevent semantically identical requests from creating separate cache entries.
- After an order mutation I update its detail entry and invalidate only affected lists for that account, not the entire cache.
- I set staleTime from product tolerance, such as 30 seconds for active orders, and treat gcTime only as memory retention.
Why interviewers ask this: A strong answer shows that cache identity and invalidation scope are designed together.
I snapshot the affected cache, apply one deterministic optimistic patch, and keep a rollback path tied to that mutation.
- In onMutate I cancel matching refetches first so an older response cannot overwrite the optimistic value.
- I patch the item in every visible page by stable ID and return the previous values as rollback context.
- On error I restore that context and show an error with a Retry action; concurrent likes need mutation IDs or commutative count logic.
- On settlement I invalidate the narrow feed and detail keys so the server result resolves any divergence.
Why interviewers ask this: The interviewer is checking whether the candidate handles races, duplicate cached copies, and rollback instead of only changing a button color.
I organize by product capability and give every feature a small public API.
- A payments module can own its screens, hooks, queries, tests, and local components under one directory.
- Other features import only payments/index exports, so internal file moves do not create repository-wide changes.
- Truly generic primitives go to shared UI, while business components stay with the feature that defines their rules.
- Cross-feature flows are composed in the app or navigation layer rather than making two features import each other.
Why interviewers ask this: The interviewer wants boundaries that support team ownership and change isolation rather than a cosmetic folder convention.
I normalize failures at both boundaries into one discriminated union before feature code sees them.
- The REST adapter maps network failures and HTTP statuses, while the TurboModule adapter maps stable native codes; neither the UI nor the adapters parse platform message text.
- Each variant carries kind, code, retryable, and safe context: timeouts and selected 5xx responses may be retryable, while validation, unsupported capability, and denied authorization are permanent until input or state changes.
- Sentry receives the normalized kind and code plus the original cause chain, release, and boundary, with no PII, tokens, request bodies, or file contents.
- An exhaustive switch with assertNever renders Retry only for retryable variants and specific actions such as Sign in or Open settings for permanent ones.
Why interviewers ask this: The interviewer is checking whether transport and native failures become one exhaustive UI contract without losing diagnostics or leaking private data.
I generate transport types from the API schema, validate responses at runtime, and map them into stable domain models.
- OpenAPI or GraphQL generation removes handwritten duplication but does not validate bytes received at runtime.
- Zod or another schema validator rejects malformed required fields at the network boundary with a reportable error.
- Version-specific DTO mappers absorb renamed or nullable fields so screens consume one domain shape.
- Discriminated unions model success and known error variants, forcing callers to handle every supported case.
Why interviewers ask this: The interviewer is checking whether the candidate knows that TypeScript types disappear at runtime and plans for API evolution.
The legacy bridge serialized batched asynchronous messages, while the New Architecture uses JSI-based typed interfaces and removes that JSON bridge bottleneck.
- Legacy calls crossed queues through serialized payloads, so chatty APIs paid copying and scheduling costs.
- TurboModules expose generated contracts through JSI and can be loaded lazily instead of registering every module at startup.
- Fabric uses the same architectural direction for rendering and supports tighter coordination with React's concurrent renderer.
- I still design coarse native APIs because direct access does not make 20 unnecessary boundary crossings free.
Why interviewers ask this: The interviewer expects current New Architecture knowledge without the false claim that JSI removes all scheduling and performance costs.
I would pass a file URI to an asynchronous TurboModule or Expo Module and process it on a bounded native worker queue.
- The JavaScript call sends the URI and small options, not a 5 MB base64 string or number array, and receives metadata or a temporary output URI.
- A promise returns the single result, typed progress events are optional, and a job ID with cancel(jobId) lets the user stop the work.
- Screen unmount or React Native runtime invalidation cancels the job, the worker checks cancellation, deletes temporary files, and schedules completion through the module boundary rather than touching UI from its thread.
- I measure duration, copies, peak RSS, and JavaScript responsiveness in release first, and add a custom JSI buffer or HostObject only if profiling proves the module boundary is the bottleneck.
Why interviewers ask this: The interviewer is checking for a level-appropriate asynchronous file API with bounded threading, low-copy transport, cancellation, and evidence before custom JSI work.
Fabric represents the tree in C++ and lets React prepare and prioritize render work before an atomic native mount.
- React can build immutable shadow-tree revisions and interrupt lower-priority render work under concurrent rendering.
- Layout and reconciliation no longer depend on the old serialized bridge protocol.
- The commit produces a consistent tree revision rather than exposing a half-applied set of updates.
- Actual UIKit or Android View mutations still obey platform main-thread rules, so Fabric does not erase the 16.7 ms frame budget.
Why interviewers ask this: The interviewer is checking whether the candidate understands Fabric beyond simply calling it a faster renderer.
I expose small typed TurboModule contracts and let the registry create each implementation only when its feature first asks for it.
- Each module groups a cohesive capability, such as biometrics or document scanning, instead of mirroring every native class.
- Codegen produces the platform interfaces, which keeps iOS, Android, and TypeScript signatures aligned.
- Expensive SDK setup happens lazily or in an explicit initialize method rather than in module construction.
- A JavaScript facade owns fallback behavior and makes unsupported platform capabilities explicit.
Why interviewers ask this: The interviewer wants to see lazy lifecycle design and cohesive contracts, not merely knowledge of the TurboModule name.
I make the TypeScript spec the narrow source of truth and stay within Codegen-supported, unambiguous types.
- The interface extends TurboModule and is obtained through TurboModuleRegistry, with required and optional methods represented deliberately.
- Structured records, nullable values, promises, callbacks, and typed events are declared explicitly instead of using any or class instances.
- Platform implementations inherit or conform to generated specs, so a missing method fails during the native build.
- CI runs Codegen and both platform compilers whenever the spec changes, catching drift before application tests.
Why interviewers ask this: The question tests whether the candidate treats Codegen as a cross-language contract rather than generated boilerplate.
Only the bounded sub-millisecond read is a possible synchronous method, while the 2-second operation must return a promise or event-driven result.
- A synchronous call blocks the JS runtime, so it must not wait on disk, network, locks, permissions, or the main thread.
- A promise maps one eventual result or error cleanly and keeps the JS event loop available.
- Long streams or repeated progress updates use typed events rather than a promise that tries to report many values.
- Native errors cross as stable codes and metadata, not platform exception text that JavaScript must parse.
Why interviewers ask this: The interviewer is checking whether the candidate chooses API shape from latency and cardinality while recognizing deadlock risks.
I expose one typed event stream with explicit subscription lifetime and throttle or batch data before it reaches JavaScript.
- The native observer starts when the first listener subscribes and stops when the last subscription is removed.
- Each event includes a timestamp and sequence number so consumers can detect stale or skipped updates.
- The module coalesces updates to the UI's actual need, such as 2 per second, instead of forwarding all 10.
- Screen cleanup removes the subscription, and tests verify that remounting 20 times still leaves one native observer.
Why interviewers ask this: A strong answer covers lifecycle, backpressure, ordering, and measurable leak prevention.
I tie the SDK resource to the native module or application lifecycle, not to each React screen mount.
- Lazy module initialization creates the SDK once for the active React Native runtime and makes repeated setup idempotent.
- The invalidation or teardown hook removes observers, closes resources, and releases callbacks when that runtime is destroyed.
- Kotlin code does not retain an Activity because Android can replace it; it uses application context and requests the current Activity only when required.
- Swift dispatches UIKit access to the main queue and keeps callback references weak where a cycle is possible.
Why interviewers ask this: The interviewer is evaluating whether the candidate understands both React Native runtime lifecycle and platform object lifetime.
I run the 80 ms computation on a native worker queue and schedule only UI changes and the final callback onto their required threads.
- UIKit and Android View mutations stay on the main thread, whose frame budget is about 16.7 ms at 60 Hz.
- CPU-heavy decoding or transformation uses a bounded worker pool so it cannot create unbounded concurrent jobs.
- Completion enters JavaScript through the React Native scheduler rather than invoking a JSI runtime from the worker directly.
- Cancellation and request IDs prevent a late result from updating a screen that has already unmounted.
Why interviewers ask this: The interviewer is checking practical thread ownership, frame-budget awareness, and safe result delivery.
I use a config plugin to apply deterministic native project changes and a development build that actually contains the BLE native code.
- Expo Go cannot load an arbitrary custom native module because its native binary is already fixed.
- The plugin modifies Info.plist, AndroidManifest, Gradle, or entitlements during prebuild without requiring manual edits after every regeneration.
- A local or EAS development build supplies the custom runtime while preserving Expo tooling and the developer menu.
- Any native dependency or plugin change requires a new binary; an OTA JavaScript update cannot add the BLE SDK.
Why interviewers ask this: The interviewer wants the candidate to distinguish Expo tooling from Expo Go and understand when native rebuilds are mandatory.
Locked questions
- 21
What does Hermes do with a 4 MB JavaScript bundle, and how would you reason about its garbage collection behavior?
gchermesjavascript - 22
A cold launch must become interactive in under 2 seconds; which startup phases would you measure before optimizing?
optimization - 23
In a monorepo with 3 packages, how should Metro resolve platform files and avoid loading a second copy of React?
monorepometroreact - 24
An app has 100 local icons at 1x, 2x, and 3x plus remote product images; how should Metro and the image pipeline handle them?
ci-cdmetro - 25
A Hermes app has 80 screens and a 25 MB JavaScript artifact; what can Metro realistically defer, and what are the limits of RAM bundles or code splitting?
artifactsmetrojavascript - 26
During a 60 Hz gesture, JavaScript performs a 50 ms JSON parse; what happens across the JS, UI, and native execution contexts?
android-componentsjavascript - 27
How would you implement a draggable card that must hold 60 fps and call JavaScript only once when the gesture ends?
javascript - 28
How would you tune a 10,000-row FlatList with fixed 72 px rows for smooth scrolling without doubling memory use?
memoryvirtualized-lists - 29
A feed displays 3000 by 3000 photos in 360 px cards; how would you prevent image decoding from exhausting memory?
memory - 30
A release-build navigation test repeats one flow 20 times and RSS grows from 180 MB to 450 MB; how do JS heap, native memory, and RSS differ?
navigationmemorydata-structures - 31
How would you configure React Navigation linking for 2 nested stacks so https://shop.example.com/products/42/reviews opens the correct tab and screen?
reactnavigationhttps - 32
A route sits 4 navigators deep; how should code reach it without manually constructing or mutating nested navigation state?
navigation - 33
How would you design an authentication flow that restores a token in 300 ms and preserves a deep link to a protected screen?
authtokensdesign - 34
A live-data screen may stay backgrounded for 30 minutes; how should AppState transitions affect timers, sockets, and refresh logic?
app-lifecycle - 35
Product asks for an exact background sync every 5 minutes on iOS and Android; what can React Native actually guarantee?
reactreact-native - 36
Design push notifications for 1 million installations where tokens rotate and the same message must not be processed twice.
designandroid-componentstokens - 37
What must be configured so 2 HTTPS domains open matching screens through iOS Universal Links and Android App Links?
confighttps - 38
A 500-dollar transfer requires biometric confirmation; how would you use an account-bound asymmetric private key without treating biometric success as server authorization?
auth - 39
A finance screen shows account numbers and recovery codes; how would you prevent leaks through screenshots, the app switcher, clipboard, logs, analytics, and backups?
backups - 40
An API rotates certificates every 60 days; would you add certificate pinning, and how would you avoid locking out old app versions?
lockingapi - 41
For a hook that fetches data and a screen that wraps a native camera, what should Jest and React Native Testing Library cover?
jestrtlcomponent-testing - 42
A team has 12 critical mobile flows and a 15-minute CI budget; when would you choose Detox, Maestro, or both?
end-to-end-testing - 43
A TurboModule implements AES operations on both platforms; which tests belong in TypeScript, XCTest, JUnit, and device-level suites?
typescriptturbo-modules - 44
How would you combine GitHub Actions, EAS Build, and Fastlane for 2 platforms, 3 environments, and a 15-minute pull-request check?
combineci-cd - 45
What signing assets are required to ship one iOS and one Android app, and which assets must survive a CI migration?
migrations - 46
An installed binary has runtime version 3.4.0, but a new build adds a native maps SDK; which code can EAS Update deliver safely?
over-the-air-updates - 47
How would you stage a risky release to 100,000 users at 5 percent, 25 percent, and 100 percent without breaking persisted data for older clients?
- 48
A release contains Hermes JavaScript, Swift, Kotlin, and native C++ code; what must reach Sentry for readable stack traces?
javascriptkotlinswift - 49
An EAS Update crashes while the same binary's embedded bundle works; which OTA provenance must every Sentry event and source map carry?
source-mapsover-the-air-updates - 50
Which performance telemetry would you add to detect a 5 percent regression across 20 device classes without collecting every session?
sessionsperformance - 51
A warm app takes 900 ms to open Reports the first time, and the route file eagerly imports a heavy chart module; how would you diagnose and reduce the navigation delay?
navigation - 52
Calling scrollToIndex(850) fails in a FlatList whose product rows have dynamic heights; how would you make the jump reliable?
virtualized-lists - 53
Typing one character into a search box causes 180 component renders and 250 ms input latency; how would you stop the render storm?
componentslatency - 54
A shared-tablet app reaches 1.8 GB of cached images after five users sign in, while the product budget is 250 MB and logout leaves the previous user's files on disk; how would you redesign the cache?
caching - 55
Pressing Sync blocks the JS thread for 1.8 seconds while 8,000 records are normalized, although the native UI thread remains responsive; how would you fix it?
responsivenormalizationconcurrency - 56
A screen transition visibly freezes for 280 ms, but JavaScript button logs appear immediately; how would you determine whether the UI thread or JavaScript thread is responsible?
concurrencyjavascript - 57
A PDF export raises the Hermes heap from 90 MB to 230 MB, then it falls to 105 MB after garbage collection; how would you distinguish an allocation spike from a retained leak?
gchermesdata-structures - 58
A TurboModule computes 50,000 sensor samples in 40 ms natively, but returning one nested JavaScript object pauses the app for 600 ms; how would you redesign the boundary?
turbo-modulesjavascript - 59
The dashboard waits 3.2 seconds because six API calls run in a waterfall even though only one depends on the login response; how would you shorten the path?
methodologyapi - 60
One commit in React Native DevTools takes 420 ms while the same action in yesterday's build took 95 ms; how would you make the profile comparison trustworthy?
reactreact-native - 61
A note is edited offline on two devices for 12 minutes, and both reconnect with revision 17; how would you prevent one device from silently overwriting the other?
- 62
A SQLite migration from version 7 to 8 rewrites 120,000 rows and fails on 3% of devices after the app is killed mid-migration; how would you make it recoverable?
migrations - 63
An optimistic Like update changes 41 to 42, the request fails after 2 seconds, and the user has already tapped again to reach 43; how would you roll back safely?
lockingrollback - 64
After editing a profile, the detail screen shows the old name for 90 seconds because the query cache is considered fresh; how would you correct the cache behavior?
queriescaching - 65
An infinite feed adds 6 duplicate posts after 500 items when two records share the same createdAt timestamp; how would you fix pagination?
pagination - 66
A 240 MB video upload reaches 68%, loses connectivity, and restarts from zero on a metered network; how would you add resume support?
- 67
Token refresh succeeds, but queued requests still send the old Authorization header because it was captured when each request object was created; how would you fix the stale-credential race?
authtokensdata-structures - 68
A device reports network connectivity after 7 minutes offline, but the first three queued writes still time out; how would you handle reconnect robustly?
data-structures - 69
A background sync has 500 records left, but the OS repeatedly kills it near record 300 and every run starts from zero; how would you make progress durable?
- 70
One local order out of 80 has invalid JSON after a crash, and parsing it now prevents the entire offline queue from loading; how would you recover?
data-structures - 71
After adding a TurboModule method, TypeScript expects getDevice(id: string) but the generated iOS code expects a number and codegen fails with 2 signature errors; what do you inspect?
typescriptcodegenturbo-modules - 72
A native method works on Android, but iOS rejects 100% of calls with 'unrecognized selector' after a Swift rename; how would you debug it?
swift - 73
Opening and closing a sensor screen 25 times causes each reading to be delivered 25 times and battery use doubles; how would you fix the native event listener leak?
- 74
A camera module crashes about 1 in 1,000 captures because it updates a preview view from a background callback; how would you correct the thread-affinity bug?
concurrencycallbacksui - 75
Camera permission works on iOS, but 18% of Android users who denied it twice see a dead button with no prompt; how would you design the permission flow?
designpermissions - 76
An Expo config plugin should add 3 permissions and one URL scheme, but after a clean prebuild the scheme is missing on iOS; how would you make the plugin reliable?
configexpopermissions - 77
Universal links open the app on iOS 70% of the time, while the other 30% open the website after a new bundle identifier was introduced; what would you verify?
- 78
After OrderDetails is renamed to Order, 6% of upgraded users restore persisted navigation state into a blank screen; how would you make restoration version-safe?
navigation - 79
Biometric login is unavailable or locked out on 12% of tested devices, but the current screen offers no fallback; how would you redesign it?
- 80
A vendor SDK exposes 40 callbacks with different Swift and Kotlin names, and two screens already depend on it; how would you wrap it for React Native?
callbackskotlinswift - 81
A release build crashes on Android API 26 for 8% of sessions, while debug builds and all iOS devices pass; how would you isolate it?
sessionsapi - 82
The app archives locally, but TestFlight rejects build 214 because the provisioning profile lacks one push entitlement; what would you check?
ios-distribution - 83
Adding one analytics SDK produces 6 duplicate-class errors in Gradle and a CocoaPods minimum-iOS conflict; how would you resolve both without random version changes?
build-toolsdependency-management - 84
A Hermes production error shows 80 minified JavaScript frames and points to bytecode offset 18432; how would you restore the original source stack?
hermesjavascript - 85
One checkout failure appears as 12 Sentry issues because messages contain order IDs, while breadcrumbs include request headers; how would you improve grouping and privacy?
- 86
A Detox checkout test fails 1 in 10 runs because it sleeps 3 seconds before looking for the receipt; how would you remove the flake?
end-to-end-testing - 87
A 7-screen Maestro onboarding flow passes in English but fails at step 5 in Russian because text and keyboard timing differ; how would you stabilize it?
onboardingend-to-end-testing - 88
Mobile CI falls from 22 to 6 minutes with a native cache, but a changed post_install hook or deployment target sometimes reuses stale pods; what must the cache fingerprint include?
hooksdeploymentcaching - 89
A fix is published as an EAS Update for runtime version 4, but 15% of production users still run runtime 3; what do those users receive and how would you get the fix to them?
over-the-air-updates - 90
At a 5% store rollout, crash-free sessions fall from 99.8% to 99.1% on Android 13 while iOS stays stable; how would you proceed?
sessions - 91
You must ship one app for 5 brands, each with different names, icons, colors, API hosts, and store identifiers, and manual setup already causes 4 mistakes per release; how would you structure it?
ownershipapiswift - 92
A shared library has 18 components, two themes, and 11 contrast failures after designers change the palette; how would you redesign the tokens?
componentsa11ydesign - 93
A new checkout is enabled for 10% of users, but offline devices keep the flag for 48 hours and analytics cannot tell who was exposed; how would you implement flags?
- 94
Three mobile clients emit 12 spellings of the purchase event, and revenue differs by 7% between dashboards; how would you define the analytics schema?
schema - 95
An accessibility audit finds 47 issues: unlabeled icons, 32-pixel tap targets, broken screen-reader order, and clipped text at 200% size; how would you prioritize the fix?
mobile-accessibilitya11yprioritization - 96
A 28-field insurance form takes 300 ms per keystroke and must restore a privacy-safe draft after 20 minutes in the background; how would you manage and persist it?
forms - 97
A GraphQL app caches 500 Product entities, but updating one product leaves the cart badge and two lists stale until restart; how would you fix the normalized cache?
normalizationgraphqlcaching - 98
A finance app stores a 30-day refresh token, supports biometric unlock, and currently logs request headers in debug builds; what threat model and storage design would you propose?
tokensthreat-modelingdesign - 99
A candidate release has just reached a 5% staged cohort; what automated 30-minute post-release gate would decide whether rollout continues?
cohorts - 100
A field-service app needs BLE scanning, 20-minute background location sessions, offline SQLite, push notifications, and launch on both stores in 12 weeks; would you choose Expo managed, prebuild, or bare React Native?
reactreact-nativeandroid-components