or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

devtools.mddom-components.mdindex.mdnative-modules.mdutilities.mdwinter-polyfills.md
tile.json

native-modules.mddocs/

Native Module System

The Expo SDK provides a comprehensive native module system that enables JavaScript code to communicate with platform-specific native implementations. This system handles module loading, type safety, web fallbacks, and cross-platform compatibility automatically.

Capabilities

Module Loading

Load native modules with different availability guarantees and error handling strategies.

/**
 * Loads a native module and throws an error if the module is not available
 * @param moduleName - Name of the native module to load
 * @returns The native module instance with full type safety
 * @throws Error if module is not available or fails to load
 */
function requireNativeModule<T>(moduleName: string): T;

/**
 * Loads a native module and returns null if the module is not available
 * @param moduleName - Name of the native module to load  
 * @returns The native module instance or null if not available
 */
function requireOptionalNativeModule<T>(moduleName: string): T | null;

Usage Examples:

import { requireNativeModule, requireOptionalNativeModule } from 'expo';

// Required module - will throw if not available
const Constants = requireNativeModule('expo-constants');
console.log('App version:', Constants.appVersion);

// Optional module - returns null if not available
const Camera = requireOptionalNativeModule('expo-camera');
if (Camera) {
  const permission = await Camera.requestCameraPermissionsAsync();
}

// With TypeScript interfaces
interface ExpoConstants {
  appVersion: string;
  deviceId: string;
  platform: {
    ios?: { platform: string; model: string; };
    android?: { versionCode: number; };
  };
}

const constants = requireNativeModule<ExpoConstants>('expo-constants');

View Manager Loading

Access native view managers for creating custom native UI components.

/**
 * Loads a native view manager for creating custom native views
 * @param viewName - Name of the native view manager
 * @returns The view manager instance for creating native views
 */
function requireNativeView(viewName: string): any;

Usage Examples:

import { requireNativeView } from 'expo';

// Load a native view manager
const CustomMapView = requireNativeView('ExpoMapView');

// Use in a React Native component
function MapComponent() {
  return (
    <CustomMapView
      style={{ flex: 1 }}
      region={{ latitude: 37.78825, longitude: -122.4324 }}
    />
  );
}

Web Module Registration

Register web implementations for native modules to enable cross-platform functionality.

/**
 * Registers a web implementation for a native module
 * @param moduleName - Name of the native module
 * @param moduleImplementation - Web-specific implementation object
 */
function registerWebModule(moduleName: string, moduleImplementation: any): void;

Usage Examples:

import { registerWebModule } from 'expo';

// Web implementation of a native module
const webLocationModule = {
  async getCurrentPositionAsync(options) {
    return new Promise((resolve, reject) => {
      navigator.geolocation.getCurrentPosition(
        (position) => resolve({
          coords: {
            latitude: position.coords.latitude,
            longitude: position.coords.longitude,
            accuracy: position.coords.accuracy,
          },
        }),
        reject,
        options
      );
    });
  },
};

// Register web implementation
registerWebModule('expo-location', webLocationModule);

App Reload

Programmatically reload the application during development or in response to updates.

/**
 * Reloads the entire application
 * @returns Promise that resolves when reload is initiated
 */
function reloadAppAsync(): Promise<void>;

Usage Examples:

import { reloadAppAsync } from 'expo';
import { Button } from 'react-native';

function DeveloperMenu() {
  const handleReload = async () => {
    try {
      await reloadAppAsync();
    } catch (error) {
      console.error('Failed to reload app:', error);
    }
  };

  return <Button title="Reload App" onPress={handleReload} />;
}

Core Module Classes

Base classes that provide the foundation for the native module system.

/**
 * Base class for all shared objects between JavaScript and native code
 */
class SharedObject {
  constructor();
  release(): void;
}

/**
 * Reference to a shared native object with automatic memory management
 */
class SharedRef<T> {
  constructor(nativeObject: T);
  get(): T | null;
  release(): void;
}

/**
 * Base class for all native modules with common functionality
 */
class NativeModule {
  constructor();
  addListener(eventName: string, listener: (...args: any[]) => void): Subscription;
  removeListeners(count: number): void;
}

Usage Examples:

import { NativeModule, SharedObject, SharedRef } from 'expo';

// Extending NativeModule for custom modules
class CustomNativeModule extends NativeModule {
  async performOperation(): Promise<string> {
    // Native module implementation
    return 'Operation complete';
  }
}

// Using SharedRef for memory management
function handleNativeResource(resourceRef: SharedRef<any>) {
  const resource = resourceRef.get();
  if (resource) {
    // Use the resource
    console.log('Resource available');
  }
  // Automatically cleaned up when SharedRef is garbage collected
}

Module Discovery

Available Bundled Modules

The Expo SDK includes these pre-configured native modules:

Core Platform Modules

  • expo-asset: Asset management and bundling
  • expo-constants: Device and app constants
  • expo-file-system: File operations and storage
  • expo-font: Font loading and management
  • expo-keep-awake: Screen wake lock functionality

Development and Configuration

  • @expo/config: Project configuration management
  • @expo/config-plugins: Configuration plugin system
  • expo-modules-autolinking: Automatic native module linking
  • expo-modules-core: Core native module functionality

Platform Integration

  • @expo/vector-icons: Icon font libraries
  • react-native-edge-to-edge: Edge-to-edge display support
  • @expo/fingerprint: Project fingerprinting and caching
  • @expo/metro-config: Metro bundler configuration

Module Loading Patterns

// Check module availability pattern
const CameraModule = requireOptionalNativeModule('expo-camera');
if (CameraModule) {
  // Camera functionality available
  const hasCameraPermission = await CameraModule.getCameraPermissionsAsync();
} else {
  // Fallback for missing camera functionality
  console.warn('Camera module not available on this platform');
}

// Required module with error handling
try {
  const Constants = requireNativeModule('expo-constants');
  console.log('Device ID:', Constants.deviceId);
} catch (error) {
  console.error('Failed to load constants module:', error);
}

// Conditional loading based on platform
import { Platform } from 'react-native';

if (Platform.OS === 'ios') {
  const iOSModule = requireOptionalNativeModule('expo-ios-specific-module');
  // iOS-specific functionality
} else if (Platform.OS === 'android') {
  const AndroidModule = requireOptionalNativeModule('expo-android-specific-module');
  // Android-specific functionality
}

Error Handling

The native module system provides several error handling patterns:

Module Not Available Errors

  • requireNativeModule throws if module cannot be loaded
  • requireOptionalNativeModule returns null for graceful fallbacks
  • Check platform compatibility before loading platform-specific modules

Runtime Errors

  • Module methods may throw platform-specific errors
  • Use try-catch blocks for operation that might fail
  • Handle permission-related errors appropriately

Development vs Production

  • In development: More detailed error messages and stack traces
  • In production: Graceful degradation when modules are unavailable
  • Use optional loading patterns for better user experience