Top 30 Advanced React Native Interview Questions and Answers
30 advanced multiple-choice React Native interview questions, the deep end: internals, failure modes, and the design calls a senior engineer is expected to defend. They come from 30 bites in the React Native library, the hardest slice of the 140 React Native interview questions in the library. Answer them here or read straight down. Every question carries the correct option, why it is correct, and a link to the bite it came from.
React Native, Expo, native modules, cross-platform
30 questions. Pick an answer, or open “Show the answer” to read it.
Answers are graded in your browser. Nothing is saved, and no XP or streak is earned here. The app keeps score.
Question 1 of 30
What is the primary effect of enabling inline requires in a React Native app?
Show the answer
Answer: a · It defers a module's evaluation until the first time it is actually used
Inline requires transform top-level imports so a module is evaluated lazily on first use, cutting startup work. It does not compile to machine code (that is closer to Hermes bytecode) nor perform tree shaking, which is a separate bundler concern.
Question 2 of 30
When a native module method reads a live device value to return to JavaScript, why should it use a Promise or callback rather than a direct return?
Show the answer
Answer: d · Because crossing the native-to-JS boundary is asynchronous, so results are delivered via promise or callback
Values crossing from native into JavaScript are delivered asynchronously, so a Promise or callback is the correct pattern. Native code can return constants synchronously via getConstants, and package registration is unrelated to whether methods are async.
Question 3 of 30
Why does a nested Text inherit color and fontSize from its parent while a nested View inherits nothing?
Show the answer
Answer: c · Text maps to platform attributed-text where spans inherit attributes, while Views are independent boxes with no general style cascade
Text inheritance reflects native attributed-text systems where text runs cascade attributes; Views are deliberately independent layout boxes with no cascade. React Native does not implement a general CSS cascade, so the first and last options are wrong.
Read the full bite: Why Text inherits styles but View does not
Question 4 of 30
Under the New Architecture, what is the most accurate primary reason StyleSheet.create outperforms inline literal styles in long lists?
Show the answer
Answer: c · It provides stable object references, avoiding per-render allocations and reducing diff and GC pressure
The durable benefit is referential stability that cuts allocations and garbage during frequent list re-renders. The bridge-ID serialization story is much diminished under Fabric and JSI, so attributing the gain primarily to it today overstates the mechanism.
Read the full bite: How StyleSheet.create reduces styling overhead
Question 5 of 30
Why can a Reanimated and Gesture Handler animation stay smooth even when the JavaScript thread is blocked?
Show the answer
Answer: d · Gesture tracking and worklet-driven animation run on the native UI thread via shared values, independent of the JS thread per frame
Worklets and shared values let per-frame gesture and animation work run on the UI thread, so a busy JS thread does not stall it. The Animated native driver is more limited and does not provide gesture-driven worklets, so equating them is incorrect.
Read the full bite: Gesture Handler and Reanimated on the UI thread
Question 6 of 30
A candidate adds a linking screens map for posts/:id but the link never opens the app. What is the most likely cause?
Show the answer
Answer: c · The native scheme or intent filter was not registered, so the OS never routes the URL
Without the iOS URL type or Android intent filter, the operating system never delivers the URL to your app, so the JS config never runs. The path syntax and param parsing are fine.
Read the full bite: Configuring deep linking to a parameterized screen
Question 7 of 30
What does react-native-screens primarily change about how a deep React Navigation stack behaves?
Show the answer
Answer: b · It detaches inactive screens from the native view hierarchy so their native views can be freed
The library backs screens with native containers and detaches inactive ones from the native tree, releasing their views. It does not necessarily unmount JS state, and it is unrelated to list virtualization.
Read the full bite: How react-native-screens optimizes a deep stack
Question 8 of 30
What makes navigation.navigate('Post', { id }) statically checked for correct route name and params?
Show the answer
Answer: c · A ParamList passed to the navigator and to the typed useNavigation generic
The ParamList maps names to param shapes; supplying it to the navigator and the useNavigation generic lets TypeScript autocomplete names and enforce params. Casting to any discards all of that.
Question 9 of 30
A row is wrapped in React.memo yet every item still re-renders when one updates. What is the most likely cause?
Show the answer
Answer: d · Inline arrow functions or freshly created objects are passed as props, giving new references each render
React.memo shallow-compares props; new references from inline functions or objects look like changes every render, so it never skips. Stabilizing props with useCallback and primitives restores the optimization.
Read the full bite: Preventing unnecessary FlatList item re-renders
Question 10 of 30
What is the correct trade-off when increasing FlatList's windowSize?
Show the answer
Answer: a · More memory but fewer blank cells during fast scrolling
windowSize sets how many viewports of items stay rendered. Larger keeps more rows mounted, reducing blanks but using more memory. initialNumToRender, not windowSize, governs the first mount.
Read the full bite: FlatList virtualization and windowing trade-offs
Question 11 of 30
Why does an inline selector that filters a list inside useSelector often cause unnecessary re-renders?
Show the answer
Answer: d · It returns a new array reference each call, so useSelector's equality check always sees a change
filter creates a fresh array every call, and useSelector uses reference equality, so it always detects a change and re-renders. useSelector uses strict equality by default, not deep comparison, ruling out that option.
Question 12 of 30
What is the main reason embedding full related objects inside each list item is discouraged in a normalized store?
Show the answer
Answer: d · Editing one entity then requires updating every duplicated copy, risking stale data
Duplicating an entity across items means a single change must be propagated everywhere, inviting inconsistency; normalization keeps one source of truth. Redux imposes no depth limit and nested objects serialize fine, so those options are false.
Question 13 of 30
What capability distinguishes a truly offline-capable architecture from one that merely caches fetched data?
Show the answer
Answer: a · A durable queue that records mutations made offline and replays them on reconnect
Offline support requires handling writes via a replayable mutation queue, not just caching reads. A bigger cache or persisting UI state does not enable offline mutations, so those options miss the core requirement.
Question 14 of 30
What single step most distinguishes a correct optimistic update from a naive one when the server request fails?
Show the answer
Answer: b · Reverting to the snapshot of state captured before the optimistic change
Optimistic UI is only correct if a failure rolls back to the pre-change snapshot, keeping the UI consistent with the server. Disabling retries, infinite resending, or nuking all state are unnecessary and harmful, so they are wrong.
Question 15 of 30
Why should queued offline mutations carry a client-generated request id when they are later replayed to the server?
Show the answer
Answer: b · So the server can deduplicate replays, preventing duplicates after an ambiguous failure
If a request succeeds but its response is lost, replaying it could create duplicates; a request id lets the server recognize and dedupe the retry. Ids are not for sorting, auth, or compression, so those options are incorrect.
Read the full bite: Offline data persistence and mutation queue
Question 16 of 30
Why does renaming a user via one mutation instantly update every screen showing that user in Apollo's normalized cache?
Show the answer
Answer: c · The entity is stored once by its cache id, so all queries reference the same record
Normalization stores each entity a single time keyed by typename and id, so updating it propagates to every query referencing it. Apollo does not auto-refetch all queries, poll, or remount components for this, so those options are wrong.
Question 17 of 30
For a high-performance map, why bridge the platform's native map view rather than building the map in JavaScript?
Show the answer
Answer: b · Native views render and handle gestures on the platform side, far outperforming a JS reimplementation
Native map views run on the platform's rendering and gesture systems, giving smooth performance a JS reimplementation cannot match. JS can render UI, props/events are still needed, and native views are platform-specific, so those options are wrong.
Question 18 of 30
Why is Platform.OS a poor way to decide whether to show a tablet layout?
Show the answer
Answer: b · Both iOS and Android run on phones and tablets, so OS alone cannot indicate form factor
Form factor depends on screen size, and each OS spans phones and tablets, so Platform.OS cannot distinguish them; useWindowDimensions and breakpoints can. Platform.OS returns 'ios' or 'android', not width, and works on both, so those are wrong.
Question 19 of 30
Inside a Reanimated worklet you need to update React component state. What is the correct approach and why?
Show the answer
Answer: a · Wrap the call as runOnJS(setState)(value) so it executes back on the JS thread
Worklets run on the UI thread runtime, so React state updates must be scheduled back to the JS thread via runOnJS. Calling setState directly fails, and runOnUI moves work the wrong direction. Mutating a shared value does not trigger React re-renders.
Question 20 of 30
A shared element transition refuses to animate between two screens. Which cause is most consistent with the views simply jumping with no morph?
Show the answer
Answer: a · The two Animated.Views use different sharedTransitionTag values, so no match is found
Reanimated pairs views only when their sharedTransitionTag strings match exactly; mismatched tags mean no interpolation, so the element just jumps. Native-stack is in fact required, and useNativeDriver is unrelated to Reanimated shared transitions.
Read the full bite: Shared element transitions with Reanimated
Question 21 of 30
Why must a method exported from a custom native module return its result via a promise, callback, or event rather than a direct return value?
Show the answer
Answer: c · The React Native bridge is asynchronous, so native results are passed back through resolve/reject, callbacks, or emitted events
The bridge between JS and native runs asynchronously, so exported methods deliver results through promises, callbacks, or events rather than synchronous returns. This is a cross-platform constraint of the legacy bridge, not an iOS-only rule.
Question 22 of 30
The app was fully terminated and the user taps a notification that launches it. Which API delivers the notification payload so you can deep-link to the right screen?
Show the answer
Answer: a · getInitialNotification, which returns the notification that launched the app from a terminated state
getInitialNotification returns the payload that cold-launched the app from termination, enabling deep-linking. onMessage fires only in the foreground, and onNotificationOpenedApp covers taps when the app was merely backgrounded, not terminated.
Read the full bite: Handling push notifications across app states
Question 23 of 30
An accelerometer view janks badly. Which architectural change most directly removes the bottleneck while keeping the indicator smooth?
Show the answer
Answer: a · Feed sensor values into shared values and animate via a useAnimatedStyle worklet on the UI thread, instead of setState per sample
Driving the visual from shared values in a worklet keeps per-frame work off the JS thread and avoids re-renders entirely. React.memo still re-renders on each state change, raising the rate worsens it, and batching setState does not stop the render storm.
Read the full bite: Streaming accelerometer data without bridge overload
Question 24 of 30
What is the fundamental way JSI improves on the legacy bridge?
Show the answer
Answer: d · It lets JS directly invoke native host objects synchronously without serialization
JSI exposes native objects to JS for direct, synchronous, serialization-free calls. Compressing or rebatching JSON still assumes the bridge model JSI eliminates.
Read the full bite: How do Fabric, TurboModules, and JSI fix bridge limits?
Question 25 of 30
Why does wrapping a long synchronous loop in a Promise fail to unblock the UI?
Show the answer
Answer: a · The loop body still executes synchronously on the single JS thread
A Promise only schedules continuations; the synchronous loop still runs on the one JS thread and blocks it. Real parallelism needs native or worker threads.
Read the full bite: How do you move a 500ms blocking task off the JS thread?
Question 26 of 30
Which pattern across two heap snapshots most reliably indicates a memory leak?
Show the answer
Answer: b · Object counts of a constructor that grow each cycle and never drop after GC
Monotonic growth that survives GC across repeated cycles signals a leak. A spike that disappears or settles is normal allocation, not a leak.
Read the full bite: How do you debug a memory leak with Hermes heap snapshots?
Question 27 of 30
Which statement correctly contrasts the legacy bridge with JSI?
Show the answer
Answer: a · The bridge is async and serialized; JSI allows direct, synchronous, serialization-free calls
The bridge is asynchronous and JSON-serialized; JSI gives JS direct host-object references for synchronous, serialization-free access. The bridge never shared memory.
Question 28 of 30
What is the key behavioral difference between a direct event and a bubbling event?
Show the answer
Answer: a · Direct events reach only the originating component; bubbling events propagate up the tree
Direct events fire only on the component that emitted them; bubbling events travel upward so ancestors can handle them. Both can carry payloads, and bubbling goes up, not down.
Read the full bite: Direct events vs bubbling events in native components
Question 29 of 30
What is a core challenge of a C++ TurboModule that does not exist in pure JS code?
Show the answer
Answer: d · You must manage native object lifetimes manually across the JS-C++ boundary
Native memory is not managed by the JS GC, so ownership and lifetimes must be handled manually. JSI calls can be synchronous, and C++ is in fact shareable across platforms.
Read the full bite: Why use a C++ TurboModule, and what are the risks?
Question 30 of 30
Why might a Detox test hang even without any explicit waits?
Show the answer
Answer: b · Uncontrolled async like a looping animation keeps the app from reaching idle
Detox waits for the app to be idle; an infinite animation or recurring async never lets it idle, so it hangs. Adding manual sleeps is the anti-pattern, not a requirement.
Read the full bite: What are the key challenges of setting up Detox E2E?
Could you explain these out loud?
That is what an interview actually tests. Tezvyn gives you questions like these with what the interviewer is really checking, the answer that lands, and the mistake that ends the conversation, in the four minutes before your next meeting.
The iPhone app is on the way
We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.
Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.