🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

@react-native-runtimes/state

Package Overview
Dependencies
Maintainers
1
Versions
2
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@react-native-runtimes/state

Cross-runtime shared state for React Native multi-runtime apps. Zustand-style API backed by a process-wide C++ singleton — reads and writes from every Hermes runtime without a JS heap boundary.

latest
Source
npmnpm
Version
0.1.0-alpha.0
Version published
Weekly downloads
371
52.67%
Maintainers
1
Weekly downloads
 
Created
Source

@react-native-runtimes/state

Small native-backed Zustand-style store for React Native runtimes that do not share a JS heap.

The package includes Android and iOS native code. Serialized state is stored in a process-wide C++ singleton and exposed through a Nitro HybridObject for synchronous reads and commits from every React runtime. The classic React Native module remains as a small event/promise shim so runtimes can be notified after another runtime commits.

import { createSharedStore } from '@react-native-runtimes/state';

type CounterAction = { type: 'inc' } | { type: 'reset' };

export const counterStore = createSharedStore({
  name: 'counter',
  initialState: { count: 0 },
  reducer(state, action: CounterAction) {
    switch (action.type) {
      case 'inc':
        return { count: state.count + 1 };
      case 'reset':
        return { count: 0 };
    }
  },
});

counterStore.dispatch({ type: 'inc' });
const count = counterStore.useStore(state => state.count);

For shared state that is updated from multiple runtimes, take a native-backed path handle from the store:

export const chatStore = createSharedStore({
  name: 'chat',
  initialState: {
    messages: {},
    reactions: {},
    settings: { theme: 'dark' },
  },
});

const messages = chatStore.path<Record<string, Message[]>>('messages');
const releaseRoomMessages = chatStore.path<Message[]>([
  'messages',
  'release-room',
]);
const settings = chatStore.path<{ theme: string }>('settings');

await releaseRoomMessages.update(items => [...(items ?? []), message]);
await settings.set({ theme: 'light' });

const messageCount = releaseRoomMessages.use(items => items?.length ?? 0);

Path strings and path arrays both become native keys. Subscribers on related paths are invalidated together, so a subscriber on messages will be notified when messages.release-room changes.

Enable native persistence when state should survive process restart:

export const preferencesStore = createSharedStore({
  name: 'preferences',
  initialState: {
    counter: { count: 0, updatedAt: null },
  },
  subtrees: ['counter'],
  persist: {
    key: 'preferences',
    version: 1,
    subtrees: ['counter'],
  },
});

Hydration uses a native getOrInit operation, so concurrent runtimes do not both observe an empty store and race to write their own initial state. If persistence is enabled, native storage is checked before the initial state is committed to the process-wide singleton.

Runtime model

  • State is serialized as JSON at the native boundary.
  • Native storage is a C++ singleton keyed by store name and path key.
  • JS uses the Nitro SharedZustandStore HybridObject when it is available and falls back to the classic SharedZustandStore native module.
  • Each path has its own state payload, revision, and lock.
  • Each React runtime receives SharedZustandStoreChanged native events.
  • Reducers currently run in the JS runtime that calls dispatch.
  • Path updates should use one writer per path, or update(...) when two runtimes may update the same path.
  • Persisted subtrees are stored as native JSON files and restored during hydration before initial state is used.

Expo

This package does not ship its own config plugin. Register it by npm name through the packages option of @react-native-runtimes/core — core reads the reactNativeRuntimes metadata declared in this package's package.json and adds ThreadedZustandPackage to the secondary runtime's package list:

// app.config.ts
export default {
  newArchEnabled: true,
  plugins: [
    ['@react-native-runtimes/core', {
      packages: ['@react-native-runtimes/state'],
    }],
  ],
};

On iOS no additional setup is needed — the Podspec and NitroModules autolinking handle everything automatically.

The package does not require Expo at runtime.

Setup

Install the package and let React Native autolink it:

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

On iOS, run CocoaPods after install:

cd ios && pod install

For manually wired secondary runtimes, include ThreadedZustandPackage in the package list used to create that runtime:

import com.nativecompose.threadedzustand.ThreadedZustandPackage

ThreadedRuntime.setExtraReactPackagesProvider {
  listOf(ThreadedZustandPackage())
}

Native contract

The fast path expects a Nitro HybridObject named SharedZustandStore with:

  • getState(storeName, subtreeKey)
  • getOrInitState(storeName, subtreeKey, initialJson, persistKey)
  • setState(storeName, subtreeKey, stateJson)
  • getRevision(storeName, subtreeKey)
  • clear(storeName, subtreeKey)
  • setPersistedState(persistKey, stateJson)
  • clearPersistedState(persistKey)

The JS package also expects a classic native module named SharedZustandStore for event broadcast and as a fallback:

  • getState(storeName)
  • getOrInitState(storeName, initialJson, persistKey)
  • setState(storeName, stateJson, source)
  • getRevision(storeName)
  • clear(storeName, source)
  • getSubtreeState(storeName, subtreeKey)
  • getOrInitSubtreeState(storeName, subtreeKey, initialJson, persistKey)
  • setSubtreeState(storeName, subtreeKey, stateJson, source)
  • getSubtreeRevision(storeName, subtreeKey)
  • clearSubtree(storeName, subtreeKey, source)
  • setPersistedState(persistKey, stateJson)
  • clearPersistedState(persistKey)
  • notifyChanged(storeName, subtreeKey, stateJson, revision, source)

The module emits SharedZustandStoreChanged to every active React runtime after commits. Android and iOS are implemented inside this package.

The next architectural step is a reducer runtime: a non-UI Hermes runtime that loads the app bundle, registers reducers, receives native actions, and commits the reduced JSON state back into this singleton. For native-module access from reducers, that runtime should be a headless RN instance rather than a raw Hermes runtime.

Keywords

react-native

FAQs

Package last updated on 27 May 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts