React Native
BlaC’s core and React bindings are platform-agnostic JavaScript — @blac/core and @blac/react install and run in React Native without modification. The one feature that needs a platform adapter is persistence: the built-in persist plugin uses IndexedDB, which does not exist in React Native. This page covers both topics.
Installation
Section titled “Installation”# npm / yarn / bunnpm install @blac/core @blac/reactuseBloc, watch, Cubit, and every other core API work the same in React Native as in the browser — write blocs and call useBloc exactly as in React getting started; only <View>/<Text> replace HTML elements in the JSX. No polyfills are needed for the core reactive machinery.
Persistence: an AsyncStorage adapter
Section titled “Persistence: an AsyncStorage adapter”The official persist plugin ships one built-in adapter, NativeIndexedDbAdapter, which needs the global indexedDB — an API that does not exist in React Native. Supply a custom adapter (see Persistence: custom storage adapter for the IndexedDbPersistAdapter interface) that wraps AsyncStorage instead:
import type { IndexedDbPersistAdapter, PersistedRecord,} from '@blac/plugin-persist';
// AsyncStorage type stub — the real type comes from// @react-native-async-storage/async-storageinterface AsyncStorageLike { getItem(key: string): Promise<string | null>; setItem(key: string, value: string): Promise<void>; removeItem(key: string): Promise<void>; getAllKeys(): Promise<readonly string[]>; multiRemove(keys: string[]): Promise<void>;}
export function createAsyncStorageAdapter( storage: AsyncStorageLike, namespace = 'blac:',): IndexedDbPersistAdapter { const prefixed = (key: string) => `${namespace}${key}`;
return { isAvailable: () => true, // AsyncStorage is always available in RN.
async get<T>(key: string): Promise<PersistedRecord<T> | null> { const raw = await storage.getItem(prefixed(key)); if (raw === null) return null; try { return JSON.parse(raw) as PersistedRecord<T>; } catch { return null; } },
async put<T>(record: PersistedRecord<T>): Promise<void> { await storage.setItem(prefixed(record.id), JSON.stringify(record)); },
async delete(key: string): Promise<void> { await storage.removeItem(prefixed(key)); },
async clear(): Promise<void> { const all = await storage.getAllKeys(); const ours = (all as string[]).filter((k) => k.startsWith(namespace)); if (ours.length > 0) await storage.multiRemove(ours); }, };}Wire it up once at startup, same as any adapter:
import { createIndexedDbPersistPlugin } from '@blac/plugin-persist';import { getPluginManager } from '@blac/core';// import AsyncStorage from '@react-native-async-storage/async-storage';
const persist = createIndexedDbPersistPlugin({ adapter: createAsyncStorageAdapter(AsyncStorage),});
persist.persist(UserSettingsCubit);getPluginManager().install(persist);Everything else — registration options, hydration status, serialization constraints — is identical to the browser plugin. See Persistence Plugin for the rest.
See also
Section titled “See also”- Persistence Plugin — full plugin API, registration options, status monitoring, and
$blac.hydration.wait() - Instance Management —
acquire,release, and the registry lifecycle - watch — observing blocs outside React (useful for imperative React Native patterns)
- Passing Inputs —
argsand instance identity