React Native Runtimes
Get started

Quick start

Go from zero to rendering on a second JS runtime in about five minutes.

This guide takes a React Native app and lands a top-level component on a second JavaScript runtime. If you already have an app set up, skip to step 2.

Before you start

Make sure you have a working native React Native environment for iOS and Android set up.

Create or open a React Native app

npx @react-native-community/cli@latest init MyApp
cd MyApp

Install the packages

npm install @react-native-runtimes/core @react-native-runtimes/state react-native-nitro-modules

react-native-nitro-modules is required — both packages are Nitro-backed.

Wrap your Metro config

The Metro plugin generates the entry that secondary runtimes load.

metro.config.js
const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config');
const { withThreadedRuntime } = require('@react-native-runtimes/core/metro');

const config = {};

module.exports = withThreadedRuntime(
  mergeConfig(getDefaultConfig(__dirname), config),
);

Then add the generated folder to .gitignore:

.gitignore
.threaded-runtime/

Load the generated entry

Require the generated entry at the top of index.js. It runs in every runtime — component requires stay lazy, so it adds nothing to main-runtime startup:

index.js
require('./.threaded-runtime/entry');

Wire up the native side

Expose ThreadedRuntime to Swift via your bridging header:

MyApp-Bridging-Header.h
#import <NativeComposeThreadedRuntime/ThreadedRuntime.h>
AppDelegate.swift
ThreadedRuntime.configure(
  withReactNativeDelegate: delegate,
  launchOptions: launchOptions
)

// Optional: warm a runtime at startup
ThreadedRuntime.prewarmRuntime("messages-runtime")
cd ios
bundle exec pod install
MainApplication.kt
import com.nativecompose.threadedruntime.ThreadedRuntime
import com.nativecompose.threadedzustand.ThreadedZustandPackage
import com.margelo.nitro.NitroModulesPackage

class MainApplication : Application(), ReactApplication {
  override fun onCreate() {
    super.onCreate()

    ThreadedRuntime.setExtraReactPackagesProvider {
      listOf(
        NitroModulesPackage(),
        ThreadedZustandPackage(),
      )
    }

    loadReactNative(this)

    // Optional: warm a runtime at startup
    ThreadedRuntime.prewarmRuntime(applicationContext, "messages-runtime")
  }
}

Render a component on the second runtime

App.tsx
import { OnRuntime } from '@react-native-runtimes/core';
import { Text, View } from 'react-native';

function MessageList({ conversationId }: { conversationId: string }) {
  // This entire component runs on 'messages-runtime'.
  return (
    <View>
      <Text>Rendering {conversationId} on a second JS runtime</Text>
    </View>
  );
}

export default function App() {
  return (
    <OnRuntime name="messages-runtime">
      <MessageList conversationId="release-room" />
    </OnRuntime>
  );
}

That's it. Rebuild the app — your MessageList now runs on its own JS runtime. The main runtime stays free for navigation, gestures, and the rest of your UI.

What just happened?

  • Metro saw OnRuntime's direct child MessageList, gave it a stable id, and registered it in the generated threaded entry.
  • The native OnRuntime view asked the runtime named messages-runtime to mount the registered component.
  • The runtime loaded the same JS bundle as your main runtime, executed the threaded entry, and rendered MessageList.

Next step

Now read the installation reference for prewarming, headless tasks, and the Metro options — or jump straight to Rendering components on a secondary runtime.

Troubleshooting

Nothing renders on the secondary runtime

Make sure your index.js requires ./.threaded-runtime/entry, and that your component is defined at module scope (not inside another component).

Build error mentioning Nitro

Verify react-native-nitro-modules is installed and pod-install ran without errors. On Android, confirm NitroModulesPackage() is in the setExtraReactPackagesProvider list.

On this page

React Native Runtimes is built with by Margelo

We build fast and beautiful apps. Contact us at margelo.com for high-end consultancy services.

Let's talk