Skip to main content

React Native engineer technical fundamentals interview questions

11 questions on technical fundamentals for react native engineer candidates. Expect prompts such as “React Native vs Flutter: fundamental architecture differences” and “How closures in JavaScript cause stale state bugs in RN hooks”, each with a worked answer outline and the follow-ups interviewers push on.

Questions

Showing 1 to 11 of 11 technical fundamentals questions.

As asked

How does React Native's approach to rendering differ from Flutter's at the fundamental level? If a recruiter asked you to explain this in two minutes to a non-technical person, what would you say?

Sample answer outline

React Native bridges JavaScript to native platform UI components (UIView, ViewGroup), so the app looks and behaves exactly like a native app because it uses the OS's own widgets. Flutter uses its own rendering engine (Skia or Impeller) to draw every pixel itself, giving total control over appearance across platforms but diverging from native widget behavior. The trade-off: React Native follows platform UI conventions automatically; Flutter is more consistent across platforms but requires manually matching platform conventions. A strong answer notes that with Fabric, React Native's rendering is now a C++ renderer that still delegates to native views, but the rendering pipeline is more tightly integrated.

Expect these follow-ups

  • When would you choose Flutter over React Native for a new project?
  • How does this difference affect accessibility support?
fundamentalsflutterarchitecturenative-renderingcomparison

As asked

Explain how JavaScript closures interact with React hooks and cause stale closure bugs. Give a concrete React Native example where a stale closure would cause incorrect behavior in a timer or event listener.

Sample answer outline

A closure captures the variables in scope at the time the function is created. In hooks, a function created in useEffect captures the state values at render time. If state changes after the effect runs but the effect is not re-run (missing dependency), the function still references the old value. Concrete example: a setInterval that logs the count state will always log 0 if count is not in the dependency array, because the callback closed over count = 0 at mount. The fix is to include count in the dependency array, or use the functional form of setState (setCount(c => c + 1)) which does not need the current value from closure.

Expect these follow-ups

  • How does the exhaustive-deps ESLint rule help catch this?
  • When is using a ref the right solution for a stale closure instead of adding to the dependency array?
fundamentalsclosureshooksjavascriptstale-state

As asked

Name at least five ways React Native's Flexbox implementation (via Yoga) differs from CSS Flexbox in a web browser. Which differences most commonly trip up developers coming from web?

Sample answer outline

Key differences: (1) flexDirection defaults to 'column' in RN vs 'row' in CSS; (2) flex accepts only a single number in RN (shorthand for flex-grow), not the three-value CSS shorthand; (3) all dimensions are unitless (density-independent pixels), no rem, em, or %; (4) position is 'relative' or 'absolute' only, no fixed or sticky; (5) overflow defaults to 'hidden' in RN (on Android especially) vs 'visible' in CSS; (6) gap is supported only from RN 0.71+. Most common trip-up is flexDirection defaulting to 'column', causing a developer to expect a horizontal layout and getting a vertical one.

Expect these follow-ups

  • How do you implement a sticky header in a ScrollView in React Native?
  • What is the equivalent of CSS z-index in React Native and what are its limitations?
fundamentalsflexboxyogalayoutcss

As asked

React Navigation handles the Android back button by default, but you have a screen with unsaved changes that needs a custom confirmation dialog before going back. How do you intercept the back press, show the dialog, and conditionally prevent navigation?

Sample answer outline

Use BackHandler.addEventListener('hardwareBackPress', handler) inside a useEffect, return true from the handler to prevent default behavior (which would normally pop the screen), show a confirmation Alert or modal, and on confirm call navigation.goBack() manually. The cleanup function must call BackHandler.removeEventListener to avoid duplicate listeners. React Navigation 6 also provides the beforeRemove event on the navigation object which catches both hardware back and gesture-based dismissal. A strong answer prefers the beforeRemove approach as it handles all dismissal paths consistently.

Expect these follow-ups

  • How does this behave differently on Android vs iOS (where there is no hardware back button)?
  • How do you test the back button behavior in Detox?
fundamentalsandroidback-buttonnavigationuser-experience

As asked

What is the difference between .catch() chaining and try/catch with async/await for handling Promise rejections? What happens in React Native if a Promise rejects and no handler is attached, and how do you catch these globally?

Sample answer outline

Both handle rejections but .catch() on a chain works for any step in the chain, while try/catch with await works only for awaited Promises in the try block. An unhandled rejection in RN (no .catch or try/catch) fires the unhandledRejection event; in older Hermes versions this was silently swallowed which made debugging difficult. You catch these globally with process.on('unhandledRejection', handler) in Node-style environments, or in RN by using ErrorUtils.setGlobalHandler and the tracking tools (Sentry's RN SDK wraps this automatically). A strong answer mentions that Promise.allSettled is safer than Promise.all when any rejection should not abort the others.

Expect these follow-ups

  • When would you use Promise.allSettled vs Promise.all?
  • How does async/await interact with React component unmounting and how do you cancel a pending await safely?
fundamentalspromisesasync-awaiterror-handlingjavascript

As asked

React Navigation uses complex generic types to type-check route params. Explain how discriminated unions and generic constraints work in TypeScript, and show how you would type a nested stack navigator's param list to get autocomplete and type errors on navigation calls.

Sample answer outline

A discriminated union uses a shared literal field (like type or name) to narrow a union type in a switch/if block. React Navigation param lists are record types mapping screen names to param shapes. To type nested navigators, you define a type for each navigator's param list and use NavigatorScreenParams to embed the nested navigator's params in the parent's param list. The useNavigation and useRoute hooks accept the typed navigator type as a generic parameter, giving autocomplete for screen names and type errors for wrong params. A strong answer shows the type alias pattern from the React Navigation docs.

Expect these follow-ups

  • What is the difference between NativeStackNavigationProp and StackNavigationProp in terms of available methods?
  • How do you type route params that are optional?
fundamentalstypescriptnavigationgenericstypes

As asked

Explain how React's diffing algorithm uses the key prop to reconcile list items, and why getting the key wrong causes performance issues or visual bugs in a FlatList in React Native.

Sample answer outline

React's reconciler diffs the previous and next virtual DOM trees, using the key prop to match components across renders. If keys are unstable (using index as key in a dynamic list), React cannot tell which item moved vs which is new, leading to unnecessary unmount/remount cycles and state loss. In FlatList, wrong keys cause cells to re-render from scratch rather than update in place, causing jank and potential flash of the wrong content. The key should be a stable, unique identifier from the data (usually the item's server ID). A strong answer mentions that keyExtractor in FlatList is the mechanism for this and that its output is used as the key for each cell view.

Expect these follow-ups

  • What happens visually if two list items have the same key?
  • How does FlashList's recyclingKey differ from FlatList's keyExtractor?
fundamentalsreactreconciliationkeysflatlist

As asked

Your native Bluetooth module needs to emit scan results continuously to JavaScript. How does the NativeEventEmitter pattern work, what is the correct way to subscribe and unsubscribe in a React component, and what is the memory leak if you do it wrong?

Sample answer outline

NativeEventEmitter wraps the native module that implements addListener and removeListeners methods. In JS, you call nativeEmitter.addListener('BleScanResult', handler) and store the subscription object. In a React component, you add the listener inside useEffect and return a cleanup function that calls subscription.remove(). The memory leak happens when you add the listener but never remove it: on component unmount, the native module keeps calling the handler on a dead component reference, and the emitter accumulates listener references without releasing them. A strong answer notes that on iOS, addListener / removeListeners must be properly implemented in the native module to avoid warnings.

Expect these follow-ups

  • How does NativeEventEmitter differ from DeviceEventEmitter?
  • How would you test that your cleanup function correctly removes the listener?
fundamentalsevent-emitternative-modulesmemory-leakshooks

As asked

What does LayoutAnimation do, how is it different from the Animated API and Reanimated, and in what scenario is it the right choice? What is the Android-specific step you must not forget?

Sample answer outline

LayoutAnimation is a one-shot API: you call LayoutAnimation.configureNext(preset) before a setState call, and React Native animates the layout change (size, position) that results from that render. It is simpler than the Animated API because you do not manage animated values, but it is less controllable (no interpolation, no interruption). It is the right choice for simple show/hide, expand/collapse scenarios. On Android you must call UIManager.setLayoutAnimationEnabledExperimental(true) in the entry point or it is silently ignored. Reanimated's Layout Animations (entering/exiting/layout props) are the modern replacement and work across both platforms without the extra Android setup.

Expect these follow-ups

  • Can you interrupt a LayoutAnimation mid-animation?
  • How do you use Reanimated's entering/exiting animations to replace LayoutAnimation?
fundamentalslayout-animationreanimatedanimationandroid

As asked

What is React Native Fast Refresh, how does it differ from Hot Module Replacement, and what kinds of code changes cause it to fall back to a full reload?

Sample answer outline

Fast Refresh (introduced in RN 0.61) re-renders only the changed component while preserving React state in hooks, unlike HMR which replaced modules without state preservation. It uses React's reconciler to update the component tree in place. Fast Refresh falls back to a full reload when: the changed file is not a React component (a utility, a config, a native module), the changed component has no default export, or when the change involves a class component that cannot be hot-patched. It also resets local state (not React state) in the component if the component's signature changes (different hooks order). A strong answer mentions that Fast Refresh is tightly integrated with Metro and Babel transform.

Expect these follow-ups

  • How do you preserve a specific piece of state across Fast Refresh cycles?
  • Why does Fast Refresh not work for native code changes?
fundamentalsfast-refreshdeveloper-experiencehmrmetro

As asked

A newly shipped animated navigation pattern feels smooth in the prototype but janky in production on mid-range Android devices. How do you diagnose and fix it?

Sample answer outline

Start by reproducing on target hardware, not a high-end design machine. Look for layout thrashing, expensive shadows or blurs, main-thread JavaScript work, large images, and animations of layout properties instead of transform or opacity. The candidate should know how to work with engineering using browser performance tools, Android profiler, or React Native performance monitors. Good fixes include simplifying the motion, moving work to the compositor or native driver, reducing overdraw, and setting a clear frame budget. Interviewers are listening for a designer who can preserve intent while cutting implementation cost.

Expect these follow-ups

  • Which visual effects are most likely to cause overdraw?
  • How do you decide whether to simplify the design or ask engineering for optimisation?
  • What performance acceptance criteria would you set before launch?
performancemobiledebugging