skip to content

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 pageshow

explore

→ has its own guide

questions

657 · 11 sections

In React Native, what does a screen reader announce for an icon-only Pressable without accessibilityLabel, and how do accessibilityLabel and accessibilityHint fix it?

level: juniorimportance: must knowfreq 68%
basics
~20 s

React 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.

open as a page

In React Native, how does Text react to the system font size setting, and what do allowFontScaling and maxFontSizeMultiplier change?

level: juniorimportance: must knowfreq 48%
basics
~10 s

Text 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.

open as a page

In React Native, why does an Image with a require() source appear without a size while a remote uri Image renders blank?

level: juniorimportance: must knowfreq 72%
basics
~20 s

A 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.

open as a page

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?

level: juniorimportance: must knowfreq 58%
basics
~20 s

resizeMode 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.

open as a page

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?

level: juniorimportance: must knowfreq 58%
basics
~10 s

Core 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.

open as a page

In an Expo project, what is a config plugin function, and how does a mod plugin like withInfoPlist change a native file?

level: juniorimportance: must knowfreq 42%
basics
~20 s

An 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.

open as a page

Which signing credentials does an EAS build need for Android and for iOS, and who holds them by default?

level: juniorimportance: must knowfreq 45%
basics
~20 s

Android 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.

open as a page

In EAS Build, what is a build profile in eas.json, and how does one Expo codebase yield development, preview and production builds?

level: juniorimportance: must knowfreq 50%
basics
~20 s

An 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.

open as a page

In an Expo project, what does eas submit do, and where does the uploaded build land on iOS and on Android by default?

level: juniorimportance: must knowfreq 55%
basics
~20 s

EAS 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.

open as a page

With EAS Update, how do you ship a typo fix to production over the air, and what do --channel, --branch and --message do?

level: juniorimportance: must knowfreq 50%
basics
~20 s

Fix 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.

open as a page

In a React Native project, when should you reset Metro's cache, which command does it, and what does the reset actually clear?

level: juniorimportance: must knowfreq 60%
basics
~20 s

Reset 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.

open as a page

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?

level: juniorimportance: must knowfreq 50%
basics
~20 s

Metro 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.

open as a page

In React Native's Metro bundler, what happens to each source file during the transformation stage, and why does it run in worker processes?

level: juniorimportance: must knowfreq 48%
basics
~20 s

Metro 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.

open as a page

After switching git branches, a React Native app fails with Metro's 'Unable to resolve module' error. How do you triage it?

level: middleimportance: must knowfreq 55%
basics
~20 s

Read 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.

open as a page

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?

level: middleimportance: must knowfreq 52%
basics
~20 s

getDefaultConfig 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.

open as a page

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?

level: middleimportance: must knowfreq 38%
basics
~10 s

Add 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.

open as a page

How does React Native Web turn StyleSheet.create styles into CSS, and what does the browser receive for a plain inline style object?

level: middleimportance: must knowfreq 40%
basics
~20 s

React 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.

open as a page

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?

level: middleimportance: must knowfreq 38%
basics
~20 s

It 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.

open as a page

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?

level: juniorimportance: should knowfreq 38%
basics
~20 s

Install 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.

open as a page

In React Native Web, which DOM elements do View and Text render, and why does a nested Text become a span?

level: juniorimportance: should knowfreq 42%
basics
~20 s

React 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.

open as a page

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?

level: juniorimportance: must knowfreq 72%
basics
~20 s

Async 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.

open as a page

Where does React Native Async Storage v3 keep data on iOS, Android and the web, and what does its lack of encryption rule out?

level: middleimportance: must knowfreq 66%
basics
~20 s

Async 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.

open as a page

In React Native Async Storage v3, how do getMany, setMany and removeMany behave, and how should you handle the AsyncStorageError they can throw?

level: middleimportance: should knowfreq 34%
basics
~20 s

getMany 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.

open as a page

What changed in React Native Async Storage v3 compared with v2, and why does the package still ship a default export?

level: middleimportance: should knowfreq 42%
basics
~20 s

Async 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.

open as a page

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?

level: seniorimportance: should knowfreq 44%
basics
~20 s

Move 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.

open as a page

What is react-native-mmkv, and why can a React Native app read from it without await, unlike Async Storage?

level: juniorimportance: must knowfreq 58%
basics
~20 s

react-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.

open as a page

How do react-native-mmkv's useMMKVString and sibling hooks keep a React Native component in sync when a stored value changes?

level: middleimportance: should knowfreq 34%
basics
~20 s

The 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.

open as a page

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?

level: middleimportance: should knowfreq 42%
basics
~20 s

Each 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.

open as a page

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?

level: seniorimportance: should knowfreq 40%
basics
~20 s

Check 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.

open as a page

What changed when react-native-mmkv became a Nitro Module in v4, and what must a React Native project change to upgrade from v3?

level: middleimportance: nice to knowfreq 22%
basics
~20 s

react-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.

open as a page

In expo-sqlite, how do you open a database and choose between execAsync, runAsync, getFirstAsync and getAllAsync for a given query?

level: juniorimportance: must knowfreq 60%
basics
~20 s

openDatabaseAsync('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.

open as a page

In an Expo app, what do expo-sqlite's SQLiteProvider and useSQLiteContext do, and what renders before the database is ready?

level: juniorimportance: must knowfreq 45%
basics
~20 s

SQLiteProvider 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.

open as a page

In expo-sqlite, why wrap several related writes in db.withTransactionAsync, and what happens when one of them throws?

level: juniorimportance: must knowfreq 48%
basics
~10 s

withTransactionAsync 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.

open as a page

Why is building an expo-sqlite query with template-string interpolation dangerous, and how do ? and $name parameter bindings prevent SQL injection?

level: middleimportance: must knowfreq 55%
basics
~20 s

Interpolated 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.

open as a page

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?

level: middleimportance: must knowfreq 40%
basics
~10 s

Open 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.

open as a page

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?

level: juniorimportance: must knowfreq 55%
basics
~20 s

Call 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.

open as a page

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?

level: seniorimportance: must knowfreq 35%
basics
~20 s

On 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.

open as a page

In expo-secure-store, what does the iOS keychainAccessible option control, and which value suits a token read by background refresh?

level: middleimportance: should knowfreq 28%
basics
~20 s

keychainAccessible 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.

open as a page

In expo-secure-store, what does requireAuthentication: true change, and how does it behave differently on iOS and Android?

level: middleimportance: should knowfreq 30%
basics
~20 s

requireAuthentication: 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.

open as a page

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?

level: seniorimportance: should knowfreq 18%
basics
~20 s

Values 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.

open as a page

In expo-file-system, what is the difference between Paths.document and Paths.cache, and which files belong in each?

level: juniorimportance: must knowfreq 52%
basics
~20 s

Paths.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.

open as a page

In expo-file-system's File class, how do you write and read file contents, and which of those calls block the JavaScript thread?

level: middleimportance: must knowfreq 42%
basics
~20 s

expo-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.

open as a page

In Expo SDK 57, how does expo-file-system's File.downloadFileAsync handle an existing destination, a 404 response, progress and cancellation?

level: middleimportance: should knowfreq 38%
basics
~20 s

File.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.

open as a page

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?

level: seniorimportance: should knowfreq 32%
basics
~20 s

Since 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().

open as a page

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?

level: seniorimportance: should knowfreq 24%
basics
~20 s

The 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.

open as a page

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?

level: juniorimportance: must knowfreq 66%
basics
~20 s

Awaiting 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.

open as a page

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?

level: juniorimportance: must knowfreq 58%
basics
~20 s

toBeOnTheScreen 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.

open as a page

In React Native Testing Library 14, how do you render a component and find an element through screen, and why must render be awaited?

level: juniorimportance: must knowfreq 58%
basics
~10 s

In 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.

open as a page

In React Native Testing Library 14, how do you type a search and press a filter chip with userEvent, and why await each call?

level: juniorimportance: must knowfreq 50%
basics
~20 s

Create 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.

open as a page

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?

level: middleimportance: must knowfreq 55%
basics
~20 s

Use 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.

open as a page

In Detox, what does element(by.id('...')) match in a React Native app, and why is it preferred over by.text?

level: juniorimportance: must knowfreq 55%
basics
~20 s

Detox'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.

open as a page

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?

level: juniorimportance: must knowfreq 55%
basics
~20 s

Detox 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.

open as a page

In Detox, how do expect's toBeVisible() and toExist() differ, and when is waitFor(...).withTimeout() the right tool instead?

level: middleimportance: must knowfreq 50%
basics
~20 s

toExist() 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().

open as a page

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?

level: middleimportance: must knowfreq 48%
basics
~20 s

A 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.

open as a page

A Detox suite for a hotel-booking app passes locally but fails on the CI runner — how do you diagnose it?

level: seniorimportance: must knowfreq 45%
basics
~20 s

Turn 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.

open as a page