Example: DOM component with 'use dom' directive
```tsx my-component.tsx (web)
'use dom';
export default function DOMComponent({ name }: { name: string }) {
return (
<div>
<h1>Hello, {name}</h1>
</div>
);
}
```
This example shows a basic DOM component using the 'use dom' directive at the top.
DOM components use @expo/dom-webview by default in SDK 56+
Starting with SDK 56, DOM components use @expo/dom-webview by default and require no additional installation. In SDK 55 and earlier, react-native-webview must be installed separately. You can opt out of @expo/dom-webview and use react-native-webview instead by passing dom={{ useExpoDOMWebView: false }} as a prop.
Required packages for DOM components without Expo Router
If not using Expo Router and Expo Web, install @expo/metro-runtime, react-dom, and react-native-web via `npx expo install @expo/metro-runtime react-dom react-native-web`. Expo Router and Expo Web users skip this step.
Importing DOM components into native code
In native component files, import the web component that uses 'use dom'; at the top. The imported component is automatically wrapped as a react-native-webview behind the scenes and can be used like any other React component.
WebView props passed via dom prop
To pass props to the underlying WebView, use the dom prop on the DOM component. This prop accepts an object with any WebView props from react-native-webview, such as scrollEnabled: false.
DOM component props must be serializable
Data sent to DOM components through props must be serializable: number, string, boolean, null, undefined, Array, or Object. Props are sent over an asynchronous bridge, so they are not updated synchronously. They are passed to the React root component, causing the entire React tree to re-render.
Native actions as top-level async functions
Pass type-safe native functions to DOM components as async functions in top-level props. These functions execute on the native side and can accept only serializable arguments and return serializable data. Functions cannot be passed as nested props or be synchronous.
Using useDOMImperativeHandle to pass refs
Use the useDOMImperativeHandle hook inside a DOM component to accept ref calls from the native side. It is similar to React's useImperativeHandle hook but does not require a ref object to be passed to it. In SDK 53+, the ref is passed as a prop directly. In SDK 52 and earlier, use forwardRef to access the ref handle.
Feature detection in DOM components with IS_DOM
Import IS_DOM from 'expo/dom' to detect if a component is running in a DOM component. process.env.EXPO_OS is always 'web' in a DOM component. Use process.env.EXPO_DOM_HOST_OS to detect the top-level platform, which is 'ios', 'android', or undefined on web.
Measuring DOM components with matchContents prop
Use dom={{ matchContents: true }} to measure the size of a DOM component automatically and resize the native view. This is useful for layouts where the DOM component needs an intrinsic size, such as centering within a parent view.
app.json and app.config files serve as Expo app config
The app config is a file named app.json, app.config.json, app.config.js, or app.config.ts located in the root project directory. It configures how Expo CLI works, generates a project's public manifest in EAS Update (similar to index.html but for native apps), and lists Expo config plugins which influence how `npx expo prebuild` generates native code.
Expo Modules API definition
The Expo Modules API is a cross-platform API for writing native modules in Kotlin and Swift to add new capabilities to apps. This API is provided by the library expo-modules-core, which is included in the expo package.
React Native Web enables cross-platform web apps
React Native Web is a high-performing abstraction on top of react-dom that enables core primitives from React Native to run in the browser. The Expo SDK and Expo CLI have first-class support for React Native Web.
Development server hosted locally at http://localhost:8081
A development server (or dev server) is started locally by running `npx expo start` from Expo CLI. It is typically hosted on http://localhost:8081 and hosts a manifest from / which the client uses to request the JavaScript bundle from the bundler.
Entry point defaults to AppEntry.js which imports App.js
The entry point usually refers to the initial JavaScript file used to load an application. In apps using Expo CLI, the default entry point is ./node_modules/expo/AppEntry.js, which simply imports the App.js file from the root project directory and registers it as the initial component in the native app.
Platform extensions in Metro bundler for platform-specific files
Platform extensions are a feature of the Metro bundler which enables users to substitute files on a per-platform basis given a specific filename. The default resolution order in @expo/metro-config is: Android uses *.android.js, *.native.js, *.js; iOS uses *.ios.js, *.native.js, *.js; Web uses *.web.js, *.js.
Repository structure for packages, apps, docs, and templates
The Expo repository is organized as follows: packages directory contains all source code for Expo modules; apps directory contains Expo projects linked to development modules with apps/expo-go containing Expo Go source code; docs directory contains source code for https://docs.expo.dev; templates directory contains template projects from npx create-expo-app; react-native-lab contains the Expo fork of react-native used to build Expo Go; guides contains in-depth tutorials for advanced topics; tools contains build and configuration tools; template-files contains templates for files requiring private keys.
Expo repository contains SDK, Modules API, Go app, CLI, Router, and documentation
The Expo repository includes the Expo SDK, Modules API, Go app, CLI, Router, documentation, and various other supporting tools.
Expo is a platform for universal native apps on Android, iOS, and web
Expo is an open-source platform for making universal native apps that run on Android, iOS, and the web. It includes a universal runtime and libraries that let you build native apps by writing React and JavaScript.
iOS development workspace is Exponent.xcworkspace not Exponent.xcodeproj
When developing iOS in the Expo repository, always open apps/expo-go/ios/Exponent.xcworkspace instead of Exponent.xcodeproj because the workspace also loads the CocoaPods dependencies.
Expo is an open-source React Native framework
Expo is an open-source React Native framework for apps that run natively on Android, iOS, and the web. It brings together mobile and web capabilities and makes developing apps easier. The framework provides file-based routing, a standard library of native modules, and enables features like live updates, instant app sharing, and web support. The `expo` npm package provides a suite of features and can be installed in nearly any React Native project. Expo has an active community.
expo-camera barcode scanning data formatting on Android
expo-camera added support for better formatted data on barcode scanning results on Android in PR #34801.
expo-localization improvements
expo-localization now includes hooks to get current locale and calendar. Changing locale on Android no longer reloads the app if the expo-localization config plugin is added to app.json. Measurement system now returns 'uk' and 'us' values on iOS 16 and higher.
expo-image-picker multiple document selection
expo-document-picker has been migrated to Expo Modules API and now supports picking multiple documents.
expo-image-picker improvements
expo-image-picker now supports choosing camera-facing type and the ability to choose preferred asset representation mode on iOS 14+. Android image picker has been updated to use a more streamlined and modern interface resembling the iOS version.
expo-sqlite async functions added
expo-sqlite now includes experimental Promise-based execAsync and transactionAsync functions.
expo-clipboard ClipboardPasteButton on iOS
On iOS, expo-clipboard now includes a native ClipboardPasteButton view that uses UIPasteControl.
expo-crypto getRandomBytesAsync uses native getRandomValues
expo-crypto's getRandomBytesAsync now uses native getRandomValues when available.
expo-blur Android support added
expo-blur now includes Android support for BlurView.
expo-network getMacAddressAsync removed
The deprecated getMacAddressAsync method has been removed from expo-network.
expo-sharing switched to UIActivityViewController
On iOS, expo-sharing switched from using UIDocumentInteractionController to UIActivityViewController which provides more features.
expo-secure-store minimum authentication tag length
On Android, expo-secure-store enforces minimum authentication tag length for the AESEncryptor for improved security.
expo-file-system UploadProgressData.totalByteSent removed
The deprecated UploadProgressData.totalByteSent field has been removed from expo-file-system.
expo-linking removed detach.scheme support
expo-linking dropped support for detach.scheme schemes (ExpoKit).
expo-notifications removed ExpoPushTokenOptions.experienceId
The deprecated ExpoPushTokenOptions.experienceId field has been removed from expo-notifications.
expo-location: Geocoding API service removed
The Geocoding API service has been removed from expo-location in SDK 48.0.0.
expo-constants: deviceYearClass and platform.ios.model removed
The long-deprecated properties `Constants.deviceYearClass` and `Constants.platform.ios.model` have been removed. These properties now live on `expo-device`.
expo-keep-awake: activateKeepAwake deprecated
`KeepAwake.activateKeepAwake` has been deprecated in favor of `KeepAwake.activateKeepAwakeAsync`. Web support was added for keep-awake functionality, including `KeepAwake.isAvailableAsync` and `KeepAwake.addListener` for observing state changes.
expo-linking: removeEventListener removed
The deprecated `Linking.removeEventListener` has been removed.
expo-crypto: new methods for randomness and digests
expo-crypto added `randomUUID` method to get a random UUIDv4 string, `getRandomValues` method to fill typed arrays, `getRandomBytes` and `getRandomBytesAsync` methods (ported from expo-random), and `digest` method to get a cryptographic digest of a typed array.
expo-document-picker: deprecated fields removed
Deprecated fields and warnings have been removed from `getDocumentAsync` in expo-document-picker.
expo-random: deprecated in favor of expo-crypto
The expo-random library has been deprecated in favor of expo-crypto, which now includes randomness functionality.
expo-notifications: projectId parameter made required
The `projectId` parameter of `getExpoPushTokenAsync` in expo-notifications has been made required as of SDK 48.0.0.
expo-image-picker: support for Android 13 granular permissions
expo-image-picker added support for granular permissions on Android 13 as documented in Android developer guidelines.
expo-media-library: support for Android 13 granular permissions
expo-media-library added support for granular permissions on Android 13 as documented in Android developer guidelines.
expo-secure-store: NSFaceIDUsageDescription key check added
A check for the `NSFaceIDUsageDescription` key was added to the `set` function in expo-secure-store.
expo-network macOS platform support
SDK 57.0.0 adds support for the macOS platform to expo-network.
expo-clipboard macOS support added
SDK 57.0.0 adds macOS support to expo-clipboard.
expo-contacts form options in SDK 57
SDK 57.0.0 adds `cancelButtonTitle` and `showsCancelButton` options to contact forms on iOS, and `preventAnimation` option to `presentCreateForm` on iOS.
expo-font web Server.resetServerContext removed in SDK 57
In SDK 57.0.0 for web, `Server.resetServerContext()` has been removed. Server-side font state is now scoped per-render via `AsyncLocalStorage`.
expo-font web Server.withServerContext for scoped font loads
In SDK 57.0.0 for web, `Server.withServerContext(callback)` has been added to scope server-side font loads per render.
expo-image-picker launchCameraAsync simulator support
In SDK 57.0.0 on iOS, `launchCameraAsync` can now be invoked on the simulator.
expo-camera iOS responsive capture and fast capture prioritization
SDK 57.0.0 enables responsive capture and fast capture prioritization on iOS for expo-camera, resulting in lower shutter lag and faster successive photo captures.
expo-modules-jsi JavaScriptError is now copyable class on iOS
In SDK 57.0.0 on iOS, `JavaScriptError` is now a copyable class conforming to `Error` (was a non-copyable struct), and `JavaScriptValue` no longer conforms to `Error`.
@expo/ui BasicTextField replaces Filled Material TextField on Android
SDK 57.0.0 replaces the Filled Material TextField component with `BasicTextField` component on Android in @expo/ui.
expo-modules-core AppContext.setRuntime signature change
In iOS, AppContext.setRuntime now takes the native React RuntimeScheduler pointer and a dispatch trampoline alongside the runtime pointer, rather than just the runtime pointer alone. This is a breaking change for code that calls setRuntime.
SharedObject.emit API deprecation and replacement
SharedObject.emit(event:arguments:) on iOS and the vararg emit on Android are deprecated in favor of new single-payload overloads. Existing single-argument call sites continue to work unchanged.
Native view config attributes now process shared objects
Native view config attributes now carry a process function that unwraps shared objects to their registry id, allowing callers to pass shared objects directly as view props instead of unwrapping them manually.
expo-modules-core Host component ignoreSafeArea property change
On iOS, Host component's ignoreSafeAreaKeyboardInsets property has been renamed to ignoreSafeArea and now accepts 'all' or 'keyboard' string values instead of a boolean.
expo-modules-core AndroidArchitecture legacy support dropped
Android legacy architecture support has been dropped in expo-modules-core.