new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

Expo & React Native · all subjects

expo-core

512 notes in this subject, read out of this brain and free to use. This is page 3 of 9.

Unsupported AppDelegate functions

App delegate functions that may cause side effects when provided are not supported yet. For example, application(_:viewControllerWithRestorationIdentifierPath:coder:) is not supported.

Objective-C not supported for AppDelegate subscribers

Objective-C classes are not supported for AppDelegate subscribers. Only Swift classes that extend ExpoAppDelegateSubscriber can be used.

ExpoAppDelegate and AppDelegate subscribers overview

To respond to iOS system events relevant to an app, such as inbound links and notifications, the app AppDelegate must inherit from ExpoAppDelegate. The React Native module API does not provide a mechanism to hook into AppDelegate methods, so the Expo Modules API provides a mechanism for libraries to subscribe to AppDelegate function calls. ExpoAppDelegate implements most functions from UIApplicationDelegate protocol and forwards their calls to all subscribers.

Register AppDelegate subscriber in module config

Register an AppDelegate subscriber by adding its class name to the apple.appDelegateSubscribers array in the expo-module.config.json file. Example: ```json { "apple": { "appDelegateSubscribers": ["AppLifecycleDelegate"] } } ```

Expo Modules API designed around Swift and Kotlin

The Expo Modules API was designed from the ground up to be used with modern native languages: Swift and Kotlin. This decision was made to help developers avoid bugs caused by unhandled null values or incorrect types, which would be caught by the compiler in these languages rather than in Objective-C.

Records allow native structs to represent JavaScript dictionaries

The Expo Modules API has a feature called Records that allows dictionaries passed from JavaScript to be represented as native structs. This provides full type safety and automatic validation, eliminating the error-prone process of manually validating each property in NSDictionary or ReadableMap.

Single API and documentation for cross-platform module development

The Expo Modules API provides one common API and documentation that simplifies development and makes it easier for a single developer to maintain a library on multiple platforms, reducing the context switching between vastly different languages and paradigms required for writing native modules.

Expo Modules API supports primitive and complex type conversion

The Expo Modules API supports automatic conversion of primitive values (Bool, Int, UInt, Float32, Double, Pair, String), complex built-in types (URL, CGPoint, UIColor, Data, java.net.URL, android.graphics.Color, kotlin.ByteArray), records (user-defined types like structs or Objects), and enums.

Convertibles enable automatic type conversion between JavaScript and platform-specific types

The Expo Modules API can automatically convert JavaScript arguments to platform-specific types through a feature called Convertibles. For example, a JavaScript object like { x: number, y: number } or an array [number, number] can be automatically converted to CoreGraphics's CGPoint for convenience.

Pre-validation and conversion of arguments from JavaScript to native

The Expo Modules API has full knowledge of the argument types that native functions expect. It can pre-validate and convert the arguments automatically, eliminating the error-prone manual validation process that was previously required with NSDictionary or ReadableMap.

Expo Modules API avoids C++ dependency

The Expo Modules API was designed to avoid the need for C++ code in libraries. The new React Native architecture is mostly written in C++, which increases build times (especially on Android), makes debugging more difficult, and adds negative impact on library performance. By being renderer-agnostic, Expo Modules libraries avoid this complexity.

Expo Modules API is renderer-agnostic for New Architecture compatibility

The Expo Modules API was designed to be renderer-agnostic so that modules do not need to know whether the app is run on React Native's new architecture or old architecture. This reduces the technical debt and cost for library developers who would otherwise need to support both architectures.

Android lifecycle listeners and iOS AppDelegate subscribers hook into app lifecycle events

Android lifecycle listeners and iOS AppDelegate subscribers are features that allow modules to hook into the lifecycle of the app without needing to spread code across MainActivity and AppDelegate classes or require users of the library to do the same.

Shared Objects keep native module state in one place

Shared Objects is a feature that keeps the source of truth for the state of a native module in one place rather than spreading it across JavaScript and native code. For example, expo-sqlite database instances are backed by Shared Objects.

experiments.autolinkingModuleResolution flag

Starting from SDK 54, you can set experiments.autolinkingModuleResolution to true in your app config to apply autolinking to Expo CLI and Metro bundler automatically. This will force dependencies that Metro resolves to match the native modules that autolinking resolves. From SDK 55, the experiments.autolinkingModuleResolution flag is enabled by default for apps in monorepos.

flags autolinking configuration option for iOS

flags is a CocoaPods configuration option for iOS that allows you to pass flags to each autolinked pod. inhibit_warnings is likely the only flag most developers want to use, to inhibit Xcode warnings produced when compiling the autolinked modules. You can refer to the CocoaPods Podfile documentation for available flags.

Expo projects are pre-configured for Autolinking

All projects created with the npx create-expo-app command are already configured to use Expo Autolinking. If your project was created using a different tool, you should see the Installing Expo modules guide to make sure your project includes all necessary changes.

Module resolution search order in Expo Autolinking

Expo Autolinking searches for candidate dependencies to autolink in four separate steps in this order: 1) For React Native modules only, it considers any dependencies in your project root's react-native.config.js that contain an explicit root path (this file is optional and doesn't exist in most Expo projects). 2) It searches all directories specified in your autolinking configuration's searchPaths option. 3) It searches local modules in the directory specified in your autolinking configuration's nativeModulesDir option, which defaults to ./modules/. 4) It resolves the dependencies of your app and any dependency or peer dependency recursively, matching the Node.js resolution algorithm.

Expo Autolinking vs React Native community CLI autolinking

Expo Autolinking differs from React Native community CLI autolinking in several ways: it comes with built-in support for monorepos, package manager workspaces, transitive dependencies, and isolated dependencies installations; it is significantly faster; it has a more complex but more reliable module resolution algorithm that matches Node.js's module resolution; it is capable of detecting duplicate dependencies, which is a common issue in monorepos; and it integrates well with Expo Modules APIs and supports React Native modules.

Autolinking module requirements

For a module to be autolinkable, the module resolution algorithm searches only for packages that contain the Expo module config file (expo-module.config.json) at the root directory, next to the package.json file. It is also necessary to include supported platforms in the platforms array. If the platform for which the autolinking algorithm is run is not present in this array, it is just skipped in the search results.

Expo Autolinking overview and purpose

Expo Autolinking is a mechanism that automates the process of linking native dependencies in Expo and React Native projects. It reduces the library installation process to the minimum, usually just installing the package from npm and re-running pod install. The core implementation is found in the expo-modules-autolinking package and is divided into three parts: a CLI command with module resolution algorithms, code that integrates with the Gradle build system for Android, and code that integrates with CocoaPods for iOS. Expo Autolinking links both Expo modules and React Native modules.

expo-modules-autolinking react-native-config command

The react-native-config command is called by the build system when autolinking React Native modules. It outputs an object with more platform-specific details for each React Native module, such as the path to gradle or podspec files. The output follows react-native.config.js format and includes root, reactNativePath, and dependencies object with platform-specific information like podspecPath, version, configurations, and scriptPhases for each dependency.

expo-modules-autolinking verify command

The verify command verifies the autolinked native modules by checking for duplicates. Warnings are shown for each conflicting, duplicate installation. Pass the --verbose option to list all autolinked native modules.

expo-modules-autolinking resolve command

The resolve command is called by the build system during the second phase of autolinking. It requires the --platform option with values apple or android. It outputs an object with more platform-specific details for each Expo module, such as the path to build.gradle or podspec files and module classes to link. The output includes packageName, packageVersion, pods (with podName and podspecDir), swiftModuleNames, modules, appDelegateSubscribers, reactDelegateHandlers, and debugOnly flag.

expo-modules-autolinking search command

The search command is called by the build system to resolve Expo modules during the first phase of autolinking. Its implementation is shared between all platforms. The output from search will contain a list of duplicates per package, if any duplicates were found. The command returns an object in JSON format with Expo modules that Expo Autolinking found, including path, version, config (contents of expo-module.config.json), and a list of conflicting duplicates for each module.

legacy_shallowReactNativeLinking autolinking configuration option

legacy_shallowReactNativeLinking is a flag that when enabled, opts you out of the new behavior introduced in SDK 54 and restores the behavior from before SDK 54. Before SDK 54, Expo Autolinking didn't search dependencies recursively and only resolved your app's direct dependencies. When enabled, this flag restores that behavior, only searching your app's direct dependencies for React Native modules. This option isn't considered when resolving Expo modules.

buildFromSource autolinking configuration option for Android

buildFromSource is a list of package names to opt out of prebuilt Expo modules on Android. For complete reference, see Prebuilt Expo Modules for Android documentation on disabling specific modules via Expo Autolinking.

include autolinking configuration option

The include option is available in SDK 55 and later. It is a list of additional package names to verify for deduplication. This is useful for utility libraries that should not be duplicated because of singleton or internal state, even when they aren't native modules. Unlike other options, per-platform include lists are merged with the root list rather than overridden.

exclude autolinking configuration option

exclude is a list of package names to exclude from autolinking. This is useful if you don't want to link some packages that specific platforms aren't using to reduce the binary size. Before SDK 54, the exclude option only applied to Expo modules and not React Native modules. React Native modules could only be excluded using a react-native.config.js file in the root directory of your project. React Native modules can be excluded by creating a react-native.config.js in the root directory and setting the platform's configuration that the module should be excluded from to null.

Dependency resolution conflicts in autolinking

Autolinking and Node resolution have different goals and can sometimes come into conflict. If your app contains duplicate installations of a native module picked up by autolinking, your JavaScript bundle may contain both versions of the native module, while autolinking and your native app will only contain one version. This might cause runtime crashes and risks incompatibilities. This is an especially common problem with isolated dependencies or monorepos.

nativeModulesDir autolinking configuration option

nativeModulesDir is a path relative to the app's root directory that Expo Autolinking should search for local modules to autolink. This option defaults to "./modules". Changing this option is only useful if you need to change the path for local Expo modules.

searchPaths autolinking configuration option

searchPaths is a list of paths relative to the app's root directory that Expo Autolinking should search for modules to autolink. It is useful when your project has a custom structure or you want to link local packages from directories different than node_modules. The paths you specify must still be structured like node_modules directories. Before SDK 54, this list defaulted to the app's node_modules directory and all node_modules directories above it in monorepos. To opt back into the old behavior, set this list to your app's node_modules directories, for example: ["../../node_modules", "./node_modules"].

Autolinking configuration precedence

The behavior of module resolution can be customized using configuration options defined in three different places, ordered from lowest to highest precedence: 1) expo.autolinking config object in application's package.json; 2) per platform overrides with expo.autolinking.android, expo.autolinking.ios, and expo.autolinking.apple objects (apple falls back to ios when apple is missing); 3) options provided to the CLI command, the use_expo_modules! method in the Podfile or useExpoModules function in settings.gradle.

Opting out of Expo Autolinking for React Native modules

Starting from SDK 52, Expo Autolinking replaces the React Native community CLI autolinking by default. To use the React Native community CLI's autolinking instead, set the environment variable EXPO_USE_COMMUNITY_AUTOLINKING=1 and add @react-native-community/cli as a dev dependency to your project. With this environment variable set, Expo Autolinking will not be used to resolve React Native modules, but will continue to autolink Expo modules.

Edit local module on Android

To edit a local Expo module on Android: (1) Open the android directory (generated by npx expo prebuild) from your project in Android Studio and wait for Gradle to sync. (2) Open modules/my-module/android/src/main/java/expo/modules/mymodule/MyModule.kt. (3) Change the hello function to return a different string. (4) Build the app by clicking the Run 'app' button and repeat this build step anytime you make changes to native code.

Windows limitation for iOS module development

If you are using Windows, you can open the example project by opening the android directory in Android Studio, but you cannot open the iOS project files.

Alternative flows for working on Expo modules

There are other flows for working on an Expo module in parallel with your application, such as using a monorepo or publishing to npm, as described in the How to use a standalone Expo module guide.

Use absolute import paths in Expo modules

You can use absolute import paths in Expo modules by applying configuration changes. See the referenced guide at expo.fyi/absolute-path-expo-modules.md for details.

Edit standalone module on iOS

To edit a standalone Expo module on iOS: (1) Under Pods > Development Pods > MyModule, open MyModule.swift. (2) Change the hello function to return a different string. (3) Build the app by clicking the Run button or pressing Cmd+R and repeat this build step anytime you make changes to native code.

Create standalone Expo module

To create a new Expo module from scratch that can be standalone and potentially published to npm, run: npm: npx create-expo-module@latest my-module | yarn: yarn create expo-module my-module | pnpm: pnpm create expo-module my-module | bun: bun create expo-module my-module. This generates the native module along with an example app for Android and iOS.

Reinstall pods after module changes

Use npx pod-install to reinstall the pods if you add new native files to the module or when you modify expo-module.config.json.

Edit local module on iOS

To edit a local Expo module on iOS: (1) Open the ios directory (generated by npx expo prebuild) in Xcode by running xed ios. (2) Under Pods > Development Pods > MyModule, open MyModule.swift. (3) Change the hello function to return a different string. (4) Build the app by clicking the Run button or pressing Cmd+R and repeat this build step anytime you make changes to native code.

Start development server for local module

To see changes reflected in the app when editing the native module, start the development server: npm: npx expo start | yarn: yarn expo start | pnpm: pnpm expo start | bun: bun expo start.

Import local module in application

Import the local module in your application (e.g., in App.js, App.tsx, or src/app/index.tsx) using the path reference, such as: import MyModule from '@/modules/my-module';

Generate native projects for local module

If your project doesn't have native projects generated (android and ios directories), run: npm: npx expo prebuild --clean | yarn: yarn expo prebuild --clean | pnpm: pnpm expo prebuild --clean | bun: bun expo prebuild --clean. If a pre-existing ios directory exists from a previous prebuild, you must reinstall the pods using npx pod-install.

Local module directory structure

After running create-expo-module, a new directory called 'modules' is created in your project with the structure: modules/my-module/android/, modules/my-module/ios/, modules/my-module/src/, modules/my-module/expo-module.config.json, modules/my-module/index.ts.

Two recommended flows to create a new module

The two recommended flows are: (1) Add a new module to an existing Expo application and use it to test and develop your module locally. (2) Create a new module in isolation with a generated example project if you want to reuse it in multiple projects or publish it to npm.

Two ways to get started with Expo Modules API

There are two ways to get started with the Expo Modules API: initialize a new module from scratch, or add the Expo Modules API to an existing module. The guide covers creating a new module from scratch, while the Integrating in an existing library guide covers adding to an existing module.

Edit standalone module on Android

To edit a standalone Expo module on Android: (1) Open my-module/android/src/main/java/expo/modules/mymodule/MyModule.kt. (2) Change the hello function to return a different string. (3) Build the app by clicking the Run 'app' button and repeat this build step anytime you make changes to native code.

iOS inline native view Swift example

For iOS, inline native views are created as Swift files in the app directory. Example FirstInlineView.swift: ```swift internal import ExpoModulesCore import WebKit class FirstInlineView: Module { public func definition() -> ModuleDefinition { View(ExpoWebView.self) { Events("onLoad") Prop("url") { (view, url: URL) in if view.webView.url != url { let urlRequest = URLRequest(url: url) view.webView.load(urlRequest) } } } } } class ExpoWebView: ExpoView, WKNavigationDelegate { let webView = WKWebView() let onLoad = EventDispatcher() required init(appContext: AppContext? = nil) { super.init(appContext: appContext) clipsToBounds = true webView.navigationDelegate = self addSubview(webView) } override func layoutSubviews() { webView.frame = bounds } func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { if let url = webView.url { onLoad([ "url": url.absoluteString ]) } } } ```

Android inline native view Kotlin example

For Android, inline native views are created as Kotlin files in the app directory. Example FirstInlineView.kt: ```kotlin package app import expo.modules.kotlin.modules.Module import expo.modules.kotlin.modules.ModuleDefinition import java.net.URL import android.content.Context import android.webkit.WebView import android.webkit.WebViewClient import expo.modules.kotlin.AppContext import expo.modules.kotlin.viewevent.EventDispatcher import expo.modules.kotlin.views.ExpoView class FirstInlineView : Module() { override fun definition() = ModuleDefinition { View(ExpoWebView::class) { Events("onLoad") Prop("url") { view: ExpoWebView, url: URL? -> view.webView.loadUrl(url.toString()) } } } } class ExpoWebView(context: Context, appContext: AppContext) : ExpoView(context, appContext) { private val onLoad by EventDispatcher() internal val webView = WebView(context).also { it.layoutParams = LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT ) it.webViewClient = object : WebViewClient() { override fun onPageFinished(view: WebView, url: String) { onLoad(mapOf("url" to url)) } } addView(it) } } ```

iOS inline module Swift example

For iOS, inline modules are created as Swift files in the app directory. Example FirstInlineModule.swift: ```swift internal import ExpoModulesCore class FirstInlineModule: Module { public func definition() -> ModuleDefinition { Constant("Hello") { return "Hello iOS inline modules!" } } } ```

Use inline module in JavaScript/TypeScript

Import and use inline modules in TypeScript/JavaScript using requireNativeModule. Example: ```tsx import { requireNativeModule } from 'expo'; import { Text } from 'react-native'; const FirstInlineModule = requireNativeModule('FirstInlineModule'); export default function InlineModulesDemoComponent() { return <Text> {FirstInlineModule.Hello} </Text>; } ```

Android inline module Kotlin example

For Android, inline modules are created as Kotlin files in the app directory. Example FirstInlineModule.kt in package app: ```kotlin package app import expo.modules.kotlin.modules.Module import expo.modules.kotlin.modules.ModuleDefinition class FirstInlineModule : Module() { override fun definition() = ModuleDefinition { Constant("Hello") { -> "Hello Android inline modules!" } } } ```

Prebuild required before using inline modules

Run the prebuild command with 'npx expo prebuild' to generate android and ios native projects with inline modules setup.

Inline modules experimental status and SDK requirement

Inline modules are experimental and available in Expo SDK 56 and later. The API is subject to breaking changes.

Inline modules watchedDirectories allowed directories

Not all directories are allowed for inline modules. Refer to the inline modules reference for information on which directories are permitted.

Enable inline modules with app config

Set the expo.experiments.inlineModules.watchedDirectories in app.json to specify directories where inline modules live. Example: {"expo": {"experiments": {"inlineModules": {"watchedDirectories": ["app"]}}}}

Use inline native view in JavaScript/TypeScript

Import and use inline native views in TypeScript/JavaScript using requireNativeView. Example: ```tsx import { requireNativeModule, requireNativeView } from 'expo'; import { StyleSheet, Text, View } from 'react-native'; const FirstInlineModule = requireNativeModule('FirstInlineModule'); const FirstInlineView = requireNativeView('FirstInlineView'); export default function InlineModulesDemoComponent() { return ( <> <View style={styles.textBox}> <Text style={styles.text}> {FirstInlineModule.Hello} </Text> </View> <FirstInlineView style={styles.inlineView} url="https://docs.expo.dev/modules/" /> </> ); } const styles = StyleSheet.create({ textBox: { height: 100, justifyContent: 'flex-end', alignItems: 'center' }, text: { fontSize: 26 }, inlineView: { flex: 1 }, }); ```

Run inline module app with Expo CLI

Run inline module apps using 'npx expo run:android' for Android or 'npx expo run:ios' for iOS to compile and run the app.

Give your agent this brain