Multi-runtime Zustand
A small Zustand-like API backed by a native C++ singleton so multiple runtimes can read and update the same state.
@react-native-runtimes/state is a small Zustand-like API backed by a native
C++ singleton. Use it when the main runtime and threaded runtimes need to
read and update the same state without pushing large props through a threaded
surface.
Dynamic paths
Create one store, then take native-backed path handles from it:
import { createSharedStore } from '@react-native-runtimes/state';
type ChatState = {
conversations: Record<string, Message[]>;
metadata: Record<string, { updatedAt: string | null }>;
};
export const chatStore = createSharedStore<ChatState>({
name: 'chat',
initialState: {
conversations: {},
metadata: {},
},
});
export function conversationMessages(conversationId: string) {
return chatStore.path<Message[]>(['conversations', conversationId]);
}The path is the native key. It can be a dot string or an array of segments:
const messages = chatStore.path<Message[]>('conversations.release-room');
const sameMessages = chatStore.path<Message[]>([
'conversations',
'release-room',
]);Tip: array vs. dot path
Arrays are safer when segments may contain dots (UUIDs, emails). Dot strings read nicer in code reviews. Pick a convention and stick with it.
Read and write
Subscribe from any runtime with path.use():
function Conversation({ conversationId }: { conversationId: string }) {
const messages = conversationMessages(conversationId).use(
value => value ?? [],
);
return <MessageList messages={messages} />;
}Write through the same path handle:
const messages = conversationMessages(conversationId);
await messages.set(nextMessages, true);
await messages.update(current => [...(current ?? []), newMessage]);The old top-level APIs still work, but new code should prefer store.path(...)
because it supports paths created from ids without declaring every slice up
front.
Reading more
- Paths — the full path API
- Persistence — surviving runtime teardown
- Locking and revisions — concurrency model