Prepare for React Native interview questions grouped by experience level.
React Native Interview Question & Answers
0-2 Years
React Native is a framework for building genuinely native mobile applications for iOS and Android using JavaScript and React, letting a single codebase target both platforms rather than writing genuinely separate native code for each one. It solves the problem of maintaining two genuinely separate codebases, one in Swift or Objective-C for iOS, one in Kotlin or Java for Android, for what's often genuinely the same application.
React Native renders genuinely actual native UI components, a real native button, a real native scroll view, rather than rendering HTML inside a WebView. This gives it genuinely native performance and look-and-feel, which a WebView-based hybrid approach typically genuinely can't match.
React is a library for building genuinely web-based user interfaces, rendering to the browser's actual DOM. React Native uses the exact same genuine component-based, declarative programming model, but renders to genuinely actual native mobile UI components instead of DOM elements.
Metro is the genuine JavaScript bundler React Native uses to actually package an application's JavaScript code and assets into a single bundle the native application can actually load and run at runtime.
View, a genuinely basic container similar to a div. Text, for displaying genuine text content. Image, for displaying an actual image. ScrollView and FlatList, for genuinely scrollable content. TextInput, for genuinely accepting user text input.
Historically through a genuine bridge, serializing data as JSON and passing it asynchronously between the JavaScript thread and the native thread. Newer React Native architecture (Fabric and TurboModules) replaces this with a genuinely more direct, synchronous communication mechanism for better performance.
View is a genuinely basic, styleable container, similar to a div in web development. On iOS it genuinely maps to a UIView, and on Android it genuinely maps to a native Android View, letting you build layout structure the same way across both platforms.
Text displays genuine text content, and it's genuinely required specifically because, unlike HTML, React Native's native View component genuinely can't render text directly, raw text has to actually be wrapped in a Text component to be genuinely displayed at all.
ScrollView renders genuinely all of its children at once, regardless of whether they're currently visible on screen, which works fine for a genuinely small, fixed amount of content. FlatList renders only the items currently visible (plus a small buffer), making it the genuinely appropriate choice for a long or genuinely dynamically-sized list.
<Image source={require('./photo.png')} /> displays a genuinely local, bundled image. <Image source={{ uri: 'https://example.com/photo.png' }} /> displays a genuinely remote image, loaded over the network, and for a remote image you typically genuinely also need to specify explicit width and height styling, since React Native genuinely can't determine those dimensions automatically ahead of time.
TextInput renders a genuinely native text input field. You'd typically pair it with a value prop and an onChangeText callback, storing the genuinely current text in component state and updating that state every time the user actually types.
A plain View genuinely has no built-in way to actually detect a touch at all. TouchableOpacity (and similar Touchable components) wraps its children with genuine touch handling built in, including a visual opacity change on press, giving genuine visual feedback that a plain View alone simply doesn't provide.
React Native uses a genuinely JavaScript-based styling system, StyleSheet.create({ ... }), with property names genuinely similar to CSS but written in camelCase, like backgroundColor instead of background-color. There's genuinely no actual CSS file or cascading stylesheet the way there is on the web.
StyleSheet.create() lets React Native genuinely validate styles ahead of time and can improve performance by allowing styles to be genuinely referenced by an ID rather than sent across the bridge as a full raw object every single time. It's the genuinely recommended, conventional pattern for defining styles.
React Native uses Flexbox for layout by default, genuinely the same conceptual model as CSS Flexbox on the web, though with a genuinely different default flexDirection, column instead of the web's default row, since a mobile screen is typically genuinely taller than it is wide.
flex: 1 tells a component to genuinely grow and fill the available remaining space within its parent container. A fixed width or height genuinely locks that dimension to an exact, specific value regardless of the available space, which doesn't automatically adapt to genuinely different screen sizes the way flex does.
Pass an array to the style prop, combining a genuinely base style with a conditional style, like style={[styles.button, isActive && styles.activeButton]}, where the conditional style is genuinely applied only when isActive is genuinely truthy.
Inline styling, passing a plain object directly, is genuinely fine for a quick, dynamic, one-off value. StyleSheet.create() is genuinely preferred for static, reusable styles, since it can improve performance and keeps style definitions genuinely organized and separate from a component's actual render logic.
React Navigation is the genuinely most widely used library for handling navigation between screens in a React Native application, since React Native genuinely doesn't include a built-in navigation solution of its own. It solves the problem of managing a genuine navigation stack, transitions between screens, and passing data between them.
A Stack Navigator manages screens in a genuinely last-in-first-out stack, similar to a web browser's own history, where navigating to a new screen genuinely pushes it onto the stack, and going back genuinely pops it off, revealing the screen underneath.
A Stack Navigator genuinely pushes and pops screens in a linear sequence, fitting a genuine drill-down flow, like a list screen leading to a detail screen. A Tab Navigator shows genuinely several top-level screens accessible through persistent tabs, typically at the bottom of the screen, letting a user switch between them directly without any actual push-pop stack behavior.
Yes, and it's a genuinely common pattern. Each individual tab in a Tab Navigator can itself contain its own genuinely separate Stack Navigator, so navigating to a detail screen from one specific tab pushes it onto that tab's own stack, while the other tabs genuinely keep their own independent navigation history intact underneath.
navigation.navigate('ScreenName') navigates to the genuinely specified screen, and navigation.navigate('ScreenName', { id: 123 }) additionally passes genuine parameters that screen can then actually read through its own route.params.
navigation.goBack() genuinely pops the current screen off the navigation stack, returning to whichever screen was genuinely displayed immediately before it.
A Drawer Navigator provides a genuinely slide-out side menu, typically revealed by swiping from the edge of the screen or tapping a menu icon. It's genuinely commonly used for an application's main navigation menu, holding several top-level destinations that don't all genuinely need to be visible as persistent tabs at once.
navigation.navigate('Details', { itemId: 42 }) passes the parameter when navigating. The receiving screen reads it back through its own route.params.itemId, giving that screen direct access to whatever data the previous screen genuinely passed along when it triggered the navigation.
The Platform module, Platform.OS === 'ios', lets you genuinely check the current platform directly inside your JavaScript code and branch behavior accordingly, without needing genuinely separate files for a small, targeted difference.
React Native automatically genuinely picks the correct file based on the running platform when you import a component without specifying the extension. This approach fits a genuinely larger difference between platforms, where an entire component's implementation genuinely differs, rather than the Platform module's approach, which fits a genuinely smaller, more targeted difference within otherwise shared code.
iOS and Android genuinely implement certain visual effects, like a shadow, using different underlying native APIs and different property names, shadowColor and related properties on iOS, versus elevation on Android. This genuine platform difference means achieving a visually consistent shadow effect often requires platform-specific styling values.
SafeAreaView automatically adds padding to keep content clear of a device's genuine physical UI elements, like the iPhone's own notch or the home indicator bar. Without it, content can be genuinely obscured by these device-specific physical features on certain devices.
Despite a genuinely shared JavaScript codebase, the two platforms render through genuinely different native components underneath, and subtle differences in default behavior, styling, or performance can genuinely surface on one platform but not the other, which only actual, direct testing on both platforms can genuinely reveal.
useState works genuinely identically in React Native as it does in web React, since it's the exact same core React library and hooks API underneath. const [count, setCount] = useState(0); declares state and its update function exactly the same way in both environments.
Props work genuinely identically to how they work in web React, passed as attributes when a component is used, like <MyComponent title='Hello' />, and read inside the child component through its own props parameter.
<Button title='Submit' onPress={handleSubmit} /> (or a Touchable component wrapping custom content) calls the genuinely specified handleSubmit function whenever the button is actually pressed, mirroring web React's onClick pattern but using onPress instead, genuinely reflecting a touch interaction rather than a mouse click.
Track each field's genuine current value in component state, typically using useState for each field or a genuinely single state object holding all of them together, updating that state through each TextInput's onChangeText callback, mirroring the genuinely controlled component pattern from web React forms.
Local state, managed with useState inside one component, is appropriate when genuinely only that component needs the data. Once multiple, unrelated screens or components genuinely need access to the same state, like a logged-in user's own profile information, it typically needs to move into a genuinely shared state solution, like Context or a dedicated state management library.
The parent passes a function down as a prop, and the child genuinely calls that function, typically with some data as an argument, whenever it needs to communicate something back up, mirroring the exact same child-to-parent communication pattern used in web React.
3-6 Years
The bridge is the genuine communication mechanism connecting the JavaScript thread, where your React code actually runs, to the native thread, where genuine platform-specific UI and APIs actually live. In the older, still widely-used architecture, it genuinely passes serialized JSON messages asynchronously between the two sides.
A native module exposes genuinely native platform functionality, written in Swift/Objective-C or Kotlin/Java, to your JavaScript code. You'd genuinely need one when a required capability isn't available through React Native's own built-in APIs or an existing genuine community library, requiring you to actually write platform-specific native code yourself.
A native module exposes genuinely non-visual native functionality, like accessing a device sensor, callable from JavaScript. A native UI component exposes a genuinely actual native visual view that can be rendered directly within a React Native component tree, like wrapping a genuinely native map view that doesn't have a pure-JavaScript equivalent available.
Every genuine message crossing the bridge has to be serialized to JSON and passed asynchronously, which adds real overhead, and this can genuinely become a real bottleneck for something requiring very frequent, rapid communication, like a smooth, continuously-updating animation driven by native gesture data.
I'd first check whether an existing React Native API or a genuinely well-maintained community library already provides that functionality, since writing and maintaining a genuinely custom native module carries real, ongoing cost. A custom native module becomes genuinely necessary only when no existing solution actually covers the specific capability genuinely needed.
keyExtractor tells FlatList how to actually generate a genuinely unique key for each item, similar to a key prop in a web React list. Without a genuinely stable, unique key, FlatList can incorrectly reuse or genuinely re-render list items when the underlying data changes, causing genuinely subtle rendering bugs.
getItemLayout lets you genuinely tell FlatList each item's exact height and position ahead of time, letting it skip the genuine measurement step it would otherwise need to perform, which can meaningfully improve scroll performance for a list where every item genuinely has the exact same, known, fixed height.
initialNumToRender controls how many items are genuinely rendered on the very first render, before any scrolling occurs. windowSize controls how much content beyond the genuinely currently visible area is kept rendered as a buffer. Tuning both can genuinely help balance initial load time against scroll smoothness for a genuinely large list.
ScrollView genuinely renders all of its children immediately, regardless of whether they're actually currently visible, which for a genuinely long list means rendering potentially hundreds of off-screen components upfront, consuming real memory and genuinely slowing down the initial render considerably.
Wrap the individual list item component in React.memo() to genuinely prevent it from re-rendering when its own props genuinely haven't changed, and ensure the actual data passed to each item is genuinely stable in reference between renders, avoiding an unnecessary re-render triggered simply by a genuinely new but equivalent object reference.
The Fetch API works genuinely identically to how it works in web JavaScript, fetch('https://api.example.com/data').then(response => response.json()), since React Native genuinely includes a Fetch implementation as part of its own core JavaScript environment.
AsyncStorage provides a genuinely simple, persistent, asynchronous key-value storage mechanism for a React Native application, letting you actually save data, like a user's own preferences, that genuinely persists even after the application is fully closed and reopened later.
AsyncStorage is genuinely simple, key-value based, and fine for a genuinely small amount of data, like settings or a small cache. A genuine database like SQLite or Realm supports genuinely structured, queryable data with relationships, fitting an application genuinely needing to store and query a larger, more genuinely complex dataset locally.
Track a boolean (or a more descriptive status value) in state, set it to true right before starting the fetch, and set it back to false once the fetch completes, whether it succeeded or failed. The component then genuinely conditionally renders a loading indicator, commonly ActivityIndicator, while that flag is genuinely true.
A dedicated data-fetching library like React Query handles caching, automatic re-fetching, and loading and error states out of the box, genuinely removing a large amount of repetitive, error-prone boilerplate compared to hand-rolling caching logic yourself with plain useEffect and useState.
A community library, like react-native-vision-camera or Expo's own camera module, provides a genuine JavaScript API for actually accessing the device's camera hardware, since React Native's own core library genuinely doesn't include camera access built in by default.
A geolocation library, like react-native-geolocation-service or Expo's own location module, exposes a genuine JavaScript API for actually requesting the device's current location, after first genuinely requesting the necessary permission from the user.
Both iOS and Android genuinely require an application to explicitly request permission before accessing a genuinely sensitive capability, protecting user privacy by ensuring an application can't silently access something like the camera or precise location without the user genuinely, explicitly consenting first.
Check the genuine permission result after requesting it, and if denied, show the user a genuinely clear explanation of why that permission is actually needed and, if appropriate, a way to actually navigate to the device's own settings to grant it manually later, rather than the feature simply, silently failing with no explanation.
Flipper is a genuine debugging platform for mobile applications, providing tools to actually inspect network requests, view application logs, and examine the genuine component tree and layout, all from a genuinely dedicated desktop application connected to a running development build.
Fast Refresh is genuinely enabled by default in a standard React Native development build, automatically reflecting a genuine code change in the running application within seconds, without needing a genuinely full application restart, which meaningfully speeds up the actual development and iteration cycle.
React Native's own built-in developer menu provides access to remote debugging (connecting to Chrome DevTools) and an in-app element inspector, and a dedicated tool like React Native Debugger or Flipper adds genuinely more specialized capability, like inspecting Redux state directly.
A development build includes genuinely extra debugging capability, like Fast Refresh and detailed error messages, at the real cost of noticeably slower performance. A release build strips that debugging overhead and applies genuine optimizations, giving a genuinely accurate picture of real-world production performance that a development build alone genuinely can't show.
6-8 Years
Deep linking lets a genuinely external link, like one from a push notification, an email, or another application, open the React Native application directly to a genuinely specific screen, rather than always launching to the application's own default home screen.
Configure a linking prop on the top-level navigator, mapping genuine URL patterns to genuinely specific screens and their parameters, letting React Navigation automatically genuinely parse an incoming URL and navigate directly to the corresponding screen with the correct genuine parameters already populated.
Context works well for state that genuinely changes infrequently and doesn't need to trigger frequent, fine-grained re-renders across a large part of the component tree. A dedicated library becomes genuinely worth the added setup once an application has genuinely complex, frequently-changing shared state across many genuinely unrelated screens.
A library like redux-persist automatically saves genuinely specified parts of the Redux store to AsyncStorage (or a genuinely faster storage engine) whenever it changes, and genuinely restores that saved state when the application actually launches again.
React Navigation can genuinely persist its own navigation state, and restoring it on app launch returns the user to genuinely the same screen (and navigation stack) they were on before the application was backgrounded or genuinely, fully closed, rather than always resetting to the initial screen.
Maintain a genuinely local source of truth, using a local database or AsyncStorage, that the UI reads from directly, and queue genuine pending changes made while offline, syncing them to the actual backend once network connectivity genuinely returns, resolving any genuine conflict that might arise from data changing on both sides in the meantime.
Hermes is a genuinely lightweight JavaScript engine optimized specifically for React Native, offering genuinely faster application startup time and a smaller application size compared to the standard JavaScriptCore engine, by precompiling JavaScript into genuinely efficient bytecode ahead of time.
An animation driven purely through repeated JavaScript state updates has to genuinely cross the bridge on every single frame, and if the JavaScript thread is genuinely busy with anything else at that moment, frames can genuinely be dropped, causing visible stutter that a genuinely native-driven animation wouldn't experience.
It offloads the actual animation execution to the native side entirely, running independently of the JavaScript thread, so the animation continues to run genuinely smoothly even if the JavaScript thread becomes genuinely busy with something else at the exact same time.
The React Native Performance Monitor (accessible through the developer menu) shows genuine frame rate and JavaScript thread usage in real time, and Flipper's own more genuinely detailed profiling tools can pinpoint exactly which specific component or operation is genuinely consuming the most time.
The JavaScript thread runs your actual application logic and React's own rendering calculations. The UI thread handles actually drawing native views to the screen and responding to touch input. Understanding the distinction matters because a busy JavaScript thread can delay updates reaching the UI thread, which is exactly why an animation driven natively, bypassing the JavaScript thread entirely, stays smooth even when JavaScript is genuinely busy.
Enable Hermes, since precompiled bytecode genuinely loads faster than parsing raw JavaScript at startup. Beyond that, deferring genuinely non-critical initialization work until after the initial screen has actually rendered, and reducing the genuinely overall JavaScript bundle size, both meaningfully reduce the time before a user actually sees a usable screen.
8-10 Years
The new architecture replaces the genuinely older asynchronous bridge with a more genuinely direct communication mechanism. Fabric is the genuinely new rendering system, handling native UI updates more efficiently and synchronously where genuinely needed. TurboModules replaces the older native module system, allowing native modules to be genuinely loaded lazily and accessed more directly.
The older system genuinely required every UI update to cross the asynchronous bridge, which could introduce genuinely noticeable latency for something requiring an immediate, synchronous native response, like a gesture-driven interaction. Fabric allows genuinely synchronous communication where needed, reducing that latency significantly.
Define a genuinely typed specification (using Flow or TypeScript) describing the module's exposed methods, then implement that specification natively in Swift/Objective-C for iOS and Kotlin/Java for Android, with TurboModules handling genuinely efficient, type-safe communication between the JavaScript and native sides based on that shared specification.
JSI is a genuinely lightweight interface allowing JavaScript to hold a genuine direct reference to a native C++ object and call its methods synchronously, without the serialization overhead the older bridge genuinely required. It's the genuinely foundational technology both Fabric and TurboModules are actually built on top of.
Write a genuine native module wrapping the SDK's own native API, exposing the genuinely specific methods the JavaScript side actually needs, handling any genuinely necessary translation between the SDK's own native data types and formats JavaScript can genuinely work with directly.
I'd weigh the actual, specific native capability genuinely required against Expo's own growing library of supported native modules. If Expo's own managed workflow genuinely covers everything the application actually needs, its genuinely simpler build and deployment process is a real, worthwhile benefit. A genuinely specific native requirement Expo doesn't support pushes toward the bare workflow, allowing genuinely full native code access.
A monorepo lets genuinely shared business logic, like API calls and validation, live in one genuinely common package consumed by both the mobile and web applications. It introduces genuine challenges around platform-specific UI components genuinely still needing to be built separately for each platform, and around managing genuinely shared dependencies and build tooling consistently across both.
Code signing cryptographically genuinely verifies an application's actual publisher and confirms it genuinely hasn't been tampered with since being signed. Both Apple's App Store and Google Play genuinely require a properly signed application before it can actually be published or installed on a genuine device.
An OTA update, using a service like CodePush, lets you push a genuinely updated JavaScript bundle directly to users' devices without requiring them to actually download a genuinely new version through the App Store or Google Play. It solves the genuine problem of a slow app store review process delaying a genuinely urgent bug fix or a minor content update.
An OTA update can genuinely only update the JavaScript bundle and any bundled assets, not any genuinely native code change, like adding a new native module or updating a native dependency, which still genuinely requires a full application store submission and review.
The pipeline genuinely builds and tests the JavaScript code on every commit, and separately builds genuinely native binaries for each platform, using a service like Fastlane to automate genuinely tedious steps like code signing and actually submitting the build to the App Store or Google Play's own beta testing tracks.
Fastlane automates genuinely repetitive mobile deployment tasks, code signing, generating a build, and actually uploading it to the App Store or Google Play, that would otherwise require a genuinely tedious, error-prone manual process repeated for every single release.
Environment-specific configuration files, selected at genuine build time based on a build flavor or scheme, let the exact same codebase produce genuinely different builds targeting a different backend environment, without manually editing configuration values by hand before every single release.
10+ Years
I'd weigh the genuine, concrete need for platform-specific, deeply native functionality or genuinely peak performance against the real benefit of a genuinely shared codebase and a team already skilled in React. For most typical business applications, React Native's own shared codebase genuinely wins, while an application with genuinely intensive graphics or hardware requirements might genuinely favor fully native development instead.
Run it incrementally, ensuring genuinely all third-party dependencies actually support the new architecture first, testing thoroughly in a genuinely lower-risk environment before rolling it out broadly, and being prepared to genuinely temporarily fall back to the older architecture for any dependency that genuinely isn't ready yet.
I check whether it's genuinely solving the real problem or just its symptom, whether native module usage is genuinely justified rather than reached for prematurely, and whether the design accounts for genuine platform differences between iOS and Android rather than assuming identical behavior everywhere.
Automate what can genuinely be automated, linting, formatting, and a genuinely required check for platform-specific testing before merging, enforced directly in CI. For architectural conventions that genuinely resist full automation, I'd document the handful of decisions that actually matter most, along with the real reasoning behind each one.
I'd weigh Expo's genuinely simpler build and deployment tooling and broader library of managed native modules against the real, occasional need for genuinely direct, custom native code access that the bare workflow provides. For most typical applications, Expo's own managed workflow genuinely covers the need, while an application with genuinely unusual native requirements pushes toward the bare workflow instead.
Crash reporting tools like Sentry or Crashlytics capture a genuine stack trace and device information at the exact moment of the crash, which is a genuinely strong starting point. I'd look for a genuine pattern across crash reports, a specific device model, OS version, or a specific action that consistently precedes the crash.
Track application startup time, screen load time, and network request success rate across genuinely real user sessions, alerting on meaningful deviation from an established baseline. A React Native application that's technically not crashing but has quietly become noticeably slower is a genuinely real problem that pure crash monitoring alone genuinely wouldn't catch.
Treat the library's own exported public API, its component props, as a genuine contract with every consuming application. Adding a genuinely new optional prop is generally safe. Changing or removing an existing one needs a documented deprecation period and direct communication before actual removal.
I'd check crash reporting immediately to genuinely identify the specific error, and if it's genuinely widespread and severe enough, consider rolling back through an OTA update if the issue is genuinely JavaScript-only, since that's dramatically faster than waiting for a genuinely new app store submission and review to actually reach affected users.
Set and actually enforce a genuine performance budget, a defined maximum acceptable bundle size and startup time, checked automatically in CI, rather than letting it silently and gradually creep up feature by feature. Regular bundle analysis catches an unexpectedly large new dependency before it ever actually ships to every single user.
This is a judgment question interviewers use to see how you reason under genuine uncertainty, not to test a specific textbook fact. A strong answer names the actual constraint that forced the decision, the realistic options that were genuinely on the table, why you picked one knowing it wasn't guaranteed to be right, and what you'd do differently with what you know now.
I'd have them genuinely test their own feature on both platforms side by side early, before it's genuinely considered done, rather than treating iOS as the genuine default and Android as an afterthought, or the reverse. Seeing a genuinely real platform difference firsthand tends to build that habit far more effectively than a general reminder alone.
I wouldn't push a full, disruptive migration immediately. I'd point to a specific, real, already-experienced performance problem the new architecture would genuinely address, and pilot the migration on a genuinely lower-risk part of the application first, showing the team a concrete, measurable improvement before asking for a broader commitment.
I'd bring the actual, concrete requirements, genuine performance needs, specific native API access, into the discussion, rather than a general, abstract preference for one approach. Most disagreements like this genuinely resolve once both sides are looking at the exact same concrete technical requirements together.
I'd translate the migration into terms leadership already tracks: a specific, already-experienced performance complaint from users tied to the older bridge's overhead, and the growing maintenance cost of staying on an architecture the ecosystem is gradually moving away from. Framed as risk reduction with a concrete, already-felt cost behind it, it competes far better for prioritization than framed as a technical upgrade for its own sake.




