This documentation is available as Markdown for AI agents and LLMs. See the full Markdown index or append .md to any documentation URL.
Expo Brownfield
Toolkit and APIs for integrating Expo into existing native applications.
expo-brownfield is a toolkit for adding React Native views to existing native Android and iOS applications. It provides:
- Built-in APIs for bi-directional communication and navigation between native and React Native apps
- Config plugin for automatic setup of brownfield targets in your Expo project
- CLI for building and publishing artifacts to Maven repositories (Android) and XCFrameworks (iOS)
Installation
If you are installing this in an existing React Native app, make sure to install expo in your project.
Usage
Communication API
The Communication API enables bi-directional, message-based communication between the native (host) app and React Native.
Sending messages from React Native to native
import * as Brownfield from 'expo-brownfield'; Brownfield.sendMessage({ type: 'MyMessage', data: { language: 'TypeScript', expo: true, platforms: ['android', 'ios'], }, });
Receiving messages from native in React Native
import * as Brownfield, { type MessageEvent } from 'expo-brownfield'; import { useEffect } from 'react'; function MyComponent() { useEffect(() => { const handleMessage = (event: MessageEvent) => { console.log('Received message:', event); }; Brownfield.addMessageListener(handleMessage); return () => { Brownfield.removeMessageListener(handleMessage); }; }, []); // ... }
Sending messages from native to React Native
import expo.modules.brownfield.BrownfieldMessaging BrownfieldMessaging.sendMessage(mapOf( "type" to "MyAndroidMessage", "timestamp" to System.currentTimeMillis(), "data" to mapOf( "platform" to "android" ) ))
import ExpoBrownfield BrownfieldMessaging.sendMessage([ "type": "MyIOSMessage", "timestamp": Date().timeIntervalSince1970, "data": [ "platform": "ios" ] ])
Receiving messages from React Native in native
import expo.modules.brownfield.BrownfieldMessaging val listenerId = BrownfieldMessaging.addListener { event -> println("Message from React Native: $event") } // Later, to remove the listener: BrownfieldMessaging.removeListener(listenerId)
import ExpoBrownfield let listenerId = BrownfieldMessaging.addListener { message in print("Message from React Native: \(message)") } // Later, to remove the listener: BrownfieldMessaging.removeListener(id: listenerId)
Configuration in app config
The expo-brownfield package provides a config plugin that can be used to configure the brownfield integration when using Continuous Native Generation (CNG). This plugin allows you to customize how your Expo project is packaged and integrated into your existing native app.
Example app.json with config plugin
Configurable properties
CLI
The expo-brownfield library includes a CLI for building and publishing to Maven repositories (Android) and XCFrameworks (iOS).
Commands
build:android
Builds and publishes the brownfield library and its dependencies to Maven repositories.
build:ios
Builds the brownfield XCFramework and copies the Hermes XCFramework to the artifacts directory.
tasks:android
Lists all available publish tasks and Maven repositories.
API
import * as Brownfield from 'expo-brownfield';
Hooks
Hook to observe and set the value of shared state for a given key.
Provides a synchronous API similar to useState.
[T | undefined, (value: T | (prev: T | undefined) => T) => void]A tuple containing the value and a function to set the value.
Methods
Gets the number of registered message listeners.
numberThe number of active message listeners.
Gets the value of shared state for a given key.
T | undefinedNavigates back to the native part of the app, dismissing the React Native view.
voidSends a message to the native side of the app. The message can be received by setting up a listener in the native code.
voidEnables or disables the native back button behavior. When enabled, pressing the back button will navigate back to the native part of the app instead of performing the default React Navigation back action.
voidSets the value of shared state for a given key.
voidEvent subscriptions
Adds a listener for messages sent from the native side of the app.
EventSubscriptionA subscription object that can be used to remove the listener.
Example
const subscription = addMessageListener((event) => { console.log('Received message from native:', event); }); // Later, to remove the listener: subscription.remove();
Adds a listener for changes to the shared state for a given key.
EventSubscriptionA subscription object that can be used to remove the listener.
Removes a specific message listener.
voidInterfaces
A subscription object that allows to conveniently remove an event listener from the emitter.