React Native Runtimes
Recipes

Chat screen on a secondary runtime

Prewarm a runtime per conversation, then open the screen on the right runtime.

const CHAT_RUNTIME_NAMES = conversations.map(
  conversation => `conversation-${conversation.id}-runtime`,
);

function ConversationPicker() {
  const [selectedId, setSelectedId] = useState<string | null>(null);

  useEffect(() => {
    if (selectedId != null) {
      return;
    }

    for (const runtimeName of CHAT_RUNTIME_NAMES) {
      void ThreadedRuntime.prewarm(runtimeName);
    }
  }, [selectedId]);

  if (selectedId) {
    return (
      <ThreadedScreen
        component={ConversationScreen}
        props={{ conversationId: selectedId }}
        runtimeName={`conversation-${selectedId}-runtime`}
      />
    );
  }

  return (
    <ConversationList
      onOpen={conversationId => {
        void ThreadedRuntime.prewarm(`conversation-${conversationId}-runtime`);
        setSelectedId(conversationId);
      }}
    />
  );
}

Why one runtime per conversation

Chat screens are stateful — composer drafts, scroll position, optimistic messages. A runtime per conversation lets you keep that state alive while the user moves between conversations, and tear it down when they leave.

Tuning the prewarm set

Prewarming every conversation is overkill for large inboxes. Common shapes:

  • Prewarm only the first N visible inbox items (5–10).
  • Prewarm the most recently opened conversations.
  • Prewarm on tap-down (touch start) rather than on tap, so the runtime starts ~50 ms earlier.

Pair this with a destroyOnUnmount on ThreadedScreen if conversations should be released as soon as the user leaves them.

On this page