React Native Ecosystem
React Native and the products around it: the Expo toolchain, the Metro bundler, React Native Web, storage libraries, and RNTL and Detox for tests. Interviews for RN roles range across all of them.
on this pageshowhide
explore
- React Native (has its own guide)437 questions
- Runtime Layers20 questions
- Turbo Modules & Codegen30 questions
- Project Setup23 questions
- Debugging & Dev Loop20 questions
- Core UI Primitives39 questions
- Virtualized Lists25 questions
- Styles & Flexbox26 questions
- Platform-Specific Code19 questions
- Assistive Tech Support19 questions
- Gestures & Motion28 questions
- Screen Navigation31 questions
- Deep Link Handling14 questions
- Push Notification Handling21 questions
- Networking & Connectivity19 questions
- App State & Data19 questions
- Mobile App Hardening26 questions
- Speed & Memory Tuning26 questions
- Unit Test Setup13 questions
- Store Release19 questions
- Expo (has its own guide)107 questions
- Workflows & Prebuild18 questions
- SDK Packages19 questions
- File-System Router25 questions
- Native Config Plugins10 questions
- EAS Build & Submit17 questions
- OTA Updates18 questions
- Metro Bundler19 questions
- Import Resolution Rules5 questions
- Transformer & Babel5 questions
- Config File Anatomy5 questions
- Cache Keys & Resets4 questions
- React Native Web15 questions
- DOM Mapping & Styles6 questions
- Browser-Only Gaps5 questions
- Bundler Alias Setup4 questions
- Async Storage5 questions
- MMKV Key-Value Store5 questions
- Expo SQLite17 questions
- Async Database API5 questions
- Transactions & Schema Versions6 questions
- Provider & Live Queries6 questions
- Expo SecureStore6 questions
- Expo File System5 questions
- React Native Testing Library20 questions
- Screen Queries & Priority5 questions
- User Event Simulation5 questions
- Awaiting UI Changes5 questions
- Built-In Assertion Matchers5 questions
- Detox21 questions
- Idle-State Waiting5 questions
- Device & App Configs5 questions
- Matchers, Actions & Expectations6 questions
- Flakiness & CI Runs5 questions
→ has its own guide
questions
657 · 11 sectionsIn React Native, what does a screen reader announce for an icon-only Pressable without accessibilityLabel, and how do accessibilityLabel and accessibilityHint fix it?
basics
~20 sReact Native builds a default label from a pressable's Text children, so an icon-only Pressable has no meaningful name and no role. Set accessibilityLabel (or aria-label) to its purpose and role='button'; use accessibilityHint only to explain a non-obvious result.
In React Native, how does Text react to the system font size setting, and what do allowFontScaling and maxFontSizeMultiplier change?
basics
~10 sText scales with the user's system font size by default because allowFontScaling is true; maxFontSizeMultiplier caps how far one Text, and the Text nested in it, may grow, while allowFontScaling={false} switches scaling off entirely.
In React Native, why does an Image with a require() source appear without a size while a remote uri Image renders blank?
basics
~20 sA require() source is a bundled asset whose width and height the bundler records, so Image sizes itself on mount. A remote uri has no known size, and React Native deliberately never sizes it after download, so without dimensions it lays out at zero.
In React Native, what do Image's resizeMode values do, which is the default, and which would you use for listing photos versus a floor plan?
basics
~20 sresizeMode sets how an Image fits a box of a different shape: cover (the default) fills and crops, contain shows everything with bands, stretch distorts, repeat tiles, center never enlarges. Listing photos suit cover; a floor plan needs contain.
In React Native 0.87, why is core SafeAreaView deprecated, and how do you keep a chat screen clear of the notch using react-native-safe-area-context?
basics
~10 sCore SafeAreaView is iOS-only, applies padding only and does not work with Android edge-to-edge, so 0.81 deprecated it. Use react-native-safe-area-context: SafeAreaProvider at the root, its SafeAreaView with edges, or useSafeAreaInsets for explicit padding.
In an Expo project, what is a config plugin function, and how does a mod plugin like withInfoPlist change a native file?
basics
~20 sAn Expo config plugin is a synchronous function that takes the app config and optional props and returns the config. A mod plugin like withInfoPlist registers an async callback that edits the parsed Info.plist during npx expo prebuild.
Which signing credentials does an EAS build need for Android and for iOS, and who holds them by default?
basics
~20 sAndroid builds are signed with a keystore (key alias and passwords); iOS builds need a distribution certificate plus an app-specific provisioning profile. By default credentialsSource is remote: EAS generates them on the first eas build and stores them encrypted on its servers.
In EAS Build, what is a build profile in eas.json, and how does one Expo codebase yield development, preview and production builds?
basics
~20 sAn EAS build profile is a named object under build in eas.json describing one kind of binary; eas build --profile <name> selects it. Keys like developmentClient, distribution, ios.simulator, env and channel make each profile's binary different.
In an Expo project, what does eas submit do, and where does the uploaded build land on iOS and on Android by default?
basics
~20 sEAS Submit is a hosted service that uploads an existing .ipa or .aab to App Store Connect or Google Play. By default an iOS build lands in TestFlight and an Android build on the internal track; nothing goes to public review automatically.
With EAS Update, how do you ship a typo fix to production over the air, and what do --channel, --branch and --message do?
basics
~20 sFix the text, then run eas update --channel production --environment production --message "Fix typo". EAS bundles the JavaScript, uploads it to the branch production points at, and compatible production builds download it on a later launch.
In a React Native project, when should you reset Metro's cache, which command does it, and what does the reset actually clear?
basics
~20 sReset Metro's cache when bundles show old code or config after a Babel, dependency or branch change. npx react-native start --reset-cache or npx expo start --clear discards the transform and file map caches, not node_modules or native builds.
In a React Native app, how does Metro decide whether an imported file is source code or an asset, and what does require('./logo.png') return?
basics
~20 sMetro classifies a file by its extension: resolver.sourceExts (js, jsx, json, ts, tsx by default) are transformed and bundled as code, resolver.assetExts (png, jpg, ttf, mp4 and more) are copied as assets. require('./logo.png') returns a numeric asset registry ID that Image resolves.
In React Native's Metro bundler, what happens to each source file during the transformation stage, and why does it run in worker processes?
basics
~20 sMetro sends each file, on its own, through a transformer in a pool of worker processes: Babel compiles JSX, TypeScript and newer syntax, then Metro records the dependencies and wraps it as a module, so files transform in parallel.
After switching git branches, a React Native app fails with Metro's 'Unable to resolve module' error. How do you triage it?
basics
~20 sRead which module failed and which file imported it. A missing package usually means node_modules still matches the old branch, so reinstall. A missing relative file is a real code change. If the file exists, restart Metro, then reset caches.
In a React Native metro.config.js, how do getDefaultConfig and mergeConfig work together, and how do you add an extra asset extension such as .glb safely?
basics
~20 sgetDefaultConfig returns React Native's complete Metro defaults and mergeConfig overlays your changes section by section. Arrays are replaced, not appended, so add .glb by spreading the default assetExts plus 'glb', never by passing ['glb'] alone.
In a webpack build of a React Native codebase, how do you alias react-native to react-native-web, and why 'react-native$' and .web.js first?
basics
~10 sAdd resolve.alias { 'react-native$': 'react-native-web' } so only the exact react-native import is swapped, and list '.web.js' before '.js' in resolve.extensions so web-specific files win over shared ones.
How does React Native Web turn StyleSheet.create styles into CSS, and what does the browser receive for a plain inline style object?
basics
~20 sReact Native Web compiles each StyleSheet.create declaration into atomic CSS: one deduplicated class per property-value pair, inserted once into a shared style sheet. A plain object that never went through create becomes an inline style attribute.
In React Native Web, what happens when shared code calls an API with no web implementation, such as Alert.alert, findNodeHandle or a native module?
basics
~20 sIt depends on the API. React Native Web throws for some (findNodeHandle), silently mocks others (Alert.alert does nothing, StatusBar renders null, NativeModules holds only UIManager) and lacks platform-only exports such as PermissionsAndroid, which arrive as undefined.
To serve an Expo app's sign-up flow in a browser, what must be installed, and how does Expo alias react-native to react-native-web on Metro?
basics
~20 sInstall react-dom, react-native-web and @expo/metro-runtime with npx expo install, then run npx expo start --web. Expo CLI's Metro resolver aliases react-native to react-native-web for the web platform, so no webpack or Babel alias is needed.
In React Native Web, which DOM elements do View and Text render, and why does a nested Text become a span?
basics
~20 sReact Native Web renders View as a div carrying a flexbox reset (column direction, no shrink) and Text as a div at the top level but a span inside another Text, so nested runs stay inline and inherit font and color.
With React Native Async Storage v3, how do you persist an onboarding-completed flag and a preferred-language object when the store only accepts strings?
basics
~20 sAsync Storage stores only strings, so serialize with JSON.stringify before setItem and JSON.parse after getItem, treating a null result as never saved. Every method returns a Promise, so await the read before deciding which screen to show.
Where does React Native Async Storage v3 keep data on iOS, Android and the web, and what does its lack of encryption rule out?
basics
~20 sAsync Storage v3 writes each instance to its own plaintext SQLite file inside the app's sandbox on iOS and Android, and to an IndexedDB database on the web. Nothing is encrypted by the library, so tokens, passwords and personal data do not belong there.
In React Native Async Storage v3, how do getMany, setMany and removeMany behave, and how should you handle the AsyncStorageError they can throw?
basics
~20 sgetMany returns an object containing every requested key, null for missing ones; setMany takes a key-to-string record; removeMany ignores absent keys. Each batch is atomic, and any failure throws AsyncStorageError, whose type property says which layer failed.
What changed in React Native Async Storage v3 compared with v2, and why does the package still ship a default export?
basics
~20 sAsync Storage v3 replaces the global singleton with isolated instances from createAsyncStorage(name), drops callbacks, the merge API and useAsyncStorage, renames multiGet/multiSet/multiRemove to getMany/setMany/removeMany, and throws AsyncStorageError. The default export stays so existing v2 data remains readable during migration.
A React Native app's Async Storage usage has grown beyond a few preferences; what signals say it is time to move data to MMKV or SQLite, and how do you migrate it safely?
basics
~20 sMove when startup waits on awaited reads (synchronous MMKV fits), when large JSON strings are rewritten for one-field changes or filtered in JavaScript (SQLite fits), or when secrets crept in. Migrate once at startup: copy, verify, write a marker, then delete the old keys.
What is react-native-mmkv, and why can a React Native app read from it without await, unlike Async Storage?
basics
~20 sreact-native-mmkv calls the native C++ MMKV library directly through JSI, so getString or set run synchronously on the JS thread and return a value, not a Promise. Async Storage's native calls are asynchronous and must be awaited.
How do react-native-mmkv's useMMKVString and sibling hooks keep a React Native component in sync when a stored value changes?
basics
~20 sThe hooks subscribe to the instance's value-changed listener through useSyncExternalStore and re-read their key synchronously whenever that key changes. Any write to the same instance id in the app, from a hook or plain code, re-renders every component using that key.
In react-native-mmkv v4, how do createMMKV's id and encryptionKey options give you separate and encrypted instances, and where should the key come from?
basics
~20 sEach createMMKV id is a separate storage, so user data and app settings live apart and can be wiped separately. encryptionKey encrypts an instance (AES-128 by default); generate the key per install and keep it in platform secure storage, never in code.
A React Native to-do app reads its list from Async Storage at startup; how do you move that data into react-native-mmkv so later launches read synchronously without losing anything?
basics
~20 sCheck a migration flag in MMKV synchronously at startup. If it is missing, show a brief loading state, copy every Async Storage value into MMKV unchanged, set the flag, then delete the old keys. Later launches read synchronously.
What changed when react-native-mmkv became a Nitro Module in v4, and what must a React Native project change to upgrade from v3?
basics
~20 sreact-native-mmkv v4 was rewritten as a Nitro Module: install react-native-nitro-modules, replace new MMKV() with createMMKV(), rename delete() to remove(), rename the Info.plist AppGroup key to AppGroupIdentifier, and rebuild natively. It needs React Native 0.76 or newer.
In expo-sqlite, how do you open a database and choose between execAsync, runAsync, getFirstAsync and getAllAsync for a given query?
basics
~20 sopenDatabaseAsync('ledger.db') returns a SQLiteDatabase. Use execAsync for unparameterised multi-statement scripts such as schema setup, runAsync for writes with bound values, getFirstAsync for one row (or null), and getAllAsync for every matching row as an array of objects.
In an Expo app, what do expo-sqlite's SQLiteProvider and useSQLiteContext do, and what renders before the database is ready?
basics
~20 sSQLiteProvider opens one database for its subtree, importing an assetSource first and then running onInit, and puts it in React context; useSQLiteContext returns it in any descendant. By default the provider renders nothing until that work finishes.
In expo-sqlite, why wrap several related writes in db.withTransactionAsync, and what happens when one of them throws?
basics
~10 swithTransactionAsync runs BEGIN, awaits your callback, then COMMIT; if the callback throws it runs ROLLBACK and rethrows. Related writes land all-or-nothing, and one commit for a batch is much faster than autocommitting every statement.
Why is building an expo-sqlite query with template-string interpolation dangerous, and how do ? and $name parameter bindings prevent SQL injection?
basics
~20 sInterpolated input can become SQL code. expo-sqlite's bound parameters (? placeholders or $name keys) compile the statement first and pass values separately, so input stays data. execAsync binds nothing, so it must never receive input.
In an Expo app, how do you make a bird-sighting log screen built on expo-sqlite update when a new sighting is saved on another screen?
basics
~10 sOpen the database with enableChangeListener: true, for example through SQLiteProvider's options, then subscribe with addDatabaseChangeListener and re-run the screen's query when an event names the sightings table. Remove the subscription on unmount.
In an Expo app, how do you save, read and delete a session token with expo-secure-store, and where does the value actually live on iOS and Android?
basics
~20 sCall SecureStore.setItemAsync(key, value) to save, getItemAsync(key) to read (it resolves null when nothing is stored) and deleteItemAsync(key) on sign-out. iOS keeps the value as a Keychain item; Android encrypts it with a Keystore key into SharedPreferences.
A user deletes and reinstalls an Expo app and is still signed in on iOS but not on Android; how does expo-secure-store explain that?
basics
~20 sOn iOS, expo-secure-store values live in the Keychain, which can survive uninstalling when the app is reinstalled with the same bundle ID. On Android the Keystore keys are deleted with the app, so values are gone, and Auto Backup is configured to exclude them.
In expo-secure-store, what does the iOS keychainAccessible option control, and which value suits a token read by background refresh?
basics
~20 skeychainAccessible sets the iOS Keychain accessibility of the stored item, meaning when it can be read. The default WHEN_UNLOCKED fails while the device is locked, so a token read by background refresh needs AFTER_FIRST_UNLOCK or its THIS_DEVICE_ONLY variant.
In expo-secure-store, what does requireAuthentication: true change, and how does it behave differently on iOS and Android?
basics
~20 srequireAuthentication: true ties the stored value to the user's biometrics, so the system prompts before releasing it. On iOS the prompt appears when reading or updating an existing value; on Android every operation requires authentication.
After a user adds a new fingerprint, an Expo app's biometric-protected expo-secure-store value reads as null; why, and how should the app recover?
basics
~20 sValues saved with requireAuthentication: true are bound to the currently enrolled biometrics, so enrolling a new fingerprint invalidates them and getItemAsync resolves null. Treat that as expired: sign the user in another way, then save a fresh value.
In expo-file-system, what is the difference between Paths.document and Paths.cache, and which files belong in each?
basics
~20 sPaths.document is the app's persistent documents directory, which the system does not clear on its own; Paths.cache is the caches directory, which the OS may purge when storage runs low. Keep irreplaceable data in document and re-creatable data in cache.
In expo-file-system's File class, how do you write and read file contents, and which of those calls block the JavaScript thread?
basics
~20 sexpo-file-system's file.write(content) is synchronous; reads come as text(), base64() and bytes() Promises plus textSync(), base64Sync() and bytesSync(). Synchronous calls run native I/O on the JavaScript thread and block it, so large files need the async reads.
In Expo SDK 57, how does expo-file-system's File.downloadFileAsync handle an existing destination, a 404 response, progress and cancellation?
basics
~20 sFile.downloadFileAsync(url, destination, options) saves a URL into a File or Directory and resolves to a File. It rejects if the target exists unless idempotent is true, rejects on a non-2xx status, reports onProgress and cancels through an AbortSignal.
After upgrading an Expo app to SDK 57, readAsStringAsync imported from expo-file-system throws at runtime; why, and how do you migrate the code?
basics
~20 sSince SDK 54 the root expo-file-system import is the File/Directory/Paths API, and old names like readAsStringAsync are stubs that warn and throw. Import them from expo-file-system/legacy to unblock, then migrate each call, for example to new File(uri).text().
An Expo app caches offline map tiles with expo-file-system and its storage keeps growing; how do you measure and clean the tile cache safely?
basics
~20 sThe OS purges Paths.cache only under storage pressure, so the app enforces its own budget: one Directory per region, measured with Directory.size and removed with delete() inside try/catch, run deferred because these calls block the JavaScript thread.
In React Native Testing Library 14, why can getByText still miss a list loaded by a mocked fetch after await render(), and what should the test use instead?
basics
~20 sAwaiting RNTL 14's render() completes the mount but does not wait for a mocked fetch to resolve, and getByText checks the tree once. Use await screen.findByText(), which retries every 50 ms until the item appears or 1000 ms pass.
With React Native Testing Library, what is the difference between toBeOnTheScreen and toBeVisible, and which one proves a survey's error message is actually shown?
basics
~20 stoBeOnTheScreen passes when the element is still attached to the rendered tree; toBeVisible also fails if it or any ancestor has display: 'none', opacity: 0, is hidden from accessibility, or sits in a Modal with visible={false}. Only toBeVisible proves the message is shown.
In React Native Testing Library 14, how do you render a component and find an element through screen, and why must render be awaited?
basics
~10 sIn RNTL 14 you write await render(<LoginScreen />), then query with screen.getByText('Welcome back'). render is async because it wraps rendering in an async act, and screen is only bound after that promise resolves.
In React Native Testing Library 14, how do you type a search and press a filter chip with userEvent, and why await each call?
basics
~20 sCreate an instance with userEvent.setup(), then await user.type(searchInput, 'dune') and await user.press(chip), and assert on the rendered result. Each call returns a Promise that settles after its events and React updates, so skipping await lets assertions run too early.
With React Native Testing Library, when do you use waitFor instead of a findBy query, and how do you change their timeout per call and globally?
basics
~20 sUse findBy* when waiting for an element to appear and waitFor for any other expectation, such as a mock being called. Pass { timeout } per call (findBy's third argument) or set configure({ asyncUtilTimeout }) for the whole suite; the default is 1000 ms.
In Detox, what does element(by.id('...')) match in a React Native app, and why is it preferred over by.text?
basics
~20 sDetox's by.id matches a native view's test identifier, which React Native sets from the testID prop. Unlike by.text, it survives copy changes and translations and is unique by design, so Detox recommends it as the default matcher.
In a Detox test, why is no sleep() needed between tapping a Draw button and asserting the results screen, and what is Detox waiting for?
basics
~20 sDetox is gray-box: code inside the app tracks in-flight network requests, short timers, animations, UI layout, the main queue and the React Native JS thread, and Detox runs each action or expectation only once all of them are idle.
In Detox, how do expect's toBeVisible() and toExist() differ, and when is waitFor(...).withTimeout() the right tool instead?
basics
~20 stoExist() passes when the element is in the native view hierarchy; toBeVisible() also needs at least 75 % of it on screen by default. expect checks once after Detox's idle sync, while waitFor polls until a timeout, which must be set with withTimeout().
In Detox, how do the devices, apps and configurations sections of .detoxrc.js let one suite run on an iOS simulator and an Android emulator?
basics
~20 sA Detox config lists devices and apps as separate named dictionaries, then defines configurations that each pair one device with one app. The same test files run against whichever pair detox build -c and detox test -c select.
A Detox suite for a hotel-booking app passes locally but fails on the CI runner — how do you diagnose it?
basics
~20 sTurn on Detox artifacts for failing tests (logs, screenshots, videos) and trace logging, upload them from CI, then compare the runner's conditions — speed, headless device, workers, data, binary — and reproduce locally with the same configuration before touching retries.