Providers
<JazzExpoProvider /> is the core component that connects your Expo application to Jazz. It handles:
- Data Synchronization: Manages connections to peers and the Jazz cloud
- Local Storage: Persists data locally between app sessions
- Schema Types: Provides APIs for the AccountSchema
- Authentication: Connects your authentication system to Jazz
Setting up the provider
Wrap your app components with the <JazzExpoProvider /> component:
// App.tsx import {function JazzExpoProvider<S extends (AccountClass<Account> & CoValueFromRaw<Account>) | CoreAccountSchema>(props: JazzProviderProps<S>): JSX.ElementJazzExpoProvider } from "jazz-tools/expo"; import {import MyAppAccountMyAppAccount } from "./schema"; export functionMyJazzProvider({function MyJazzProvider({ children }: { children: React.ReactNode; }): React.JSX.Elementchildren: React.ReactNodechildren }: {children: React.ReactNodechildren:export namespace ReactReact.type React.ReactNode = string | number | bigint | boolean | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | React.ReactPortal | Promise<...> | null | undefinedRepresents all of the things React can render. Where {@link ReactElement } only represents JSX, `ReactNode` represents everything that can be rendered.ReactNode }) { return ( <function JazzExpoProvider<S extends (AccountClass<Account> & CoValueFromRaw<Account>) | CoreAccountSchema>(props: JazzProviderProps<S>): JSX.ElementJazzExpoProvidersync: SyncConfigsync={{peer: "wss://cloud.jazz.tools/?key=you@example.com"peer: `wss://cloud.jazz.tools/?key=${const apiKey: "you@example.com"Use your email as a temporary key, or get a free API Key at dashboard.jazz.tools for higher limits.apiKey}` }}AccountSchema?: anyAccountSchema={import MyAppAccountMyAppAccount} > {children: React.ReactNodechildren} </function JazzExpoProvider<S extends (AccountClass<Account> & CoValueFromRaw<Account>) | CoreAccountSchema>(props: JazzProviderProps<S>): JSX.ElementJazzExpoProvider> ); }
Sign up for a free API key at dashboard.jazz.tools for higher limits or production use, or use your email address as a temporary key to get started quickly.
Provider Options
kvStoreExpoSecureStoreAdapter(default)
AccountSchemaAccount(default)
CryptoProviderPureJSCrypto(default) - Pure JavaScript crypto providerRNQuickCrypto- C++ accelerated crypto provider
Authentication in the Provider
<JazzExpoProvider /> works with various authentication methods, with PassphraseAuth being the easiest way to get started for development and testing. For authentication details, refer to our Authentication Overview guide.
The authentication hooks must always be used inside the <JazzExpoProvider /> component.
Implementing PassphraseAuth is straightforward:
- Import the wordlist for generating recovery phrases
- Use the
usePassphraseAuthhook to handle authentication - Create simple registration and sign-in screens
// Example with PassphraseAuth import {function JazzExpoProvider<S extends (AccountClass<Account> & CoValueFromRaw<Account>) | CoreAccountSchema>(props: JazzProviderProps<S>): JSX.ElementJazzExpoProvider,function usePassphraseAuth({ wordlist }: { wordlist: string[]; }): { readonly state: "anonymous" | "signedIn"; readonly logIn: (passphrase: string) => Promise<void>; readonly signUp: (name?: string) => Promise<string>; readonly registerNewAccount: (passphrase: string, name: string) => Promise<string>; readonly generateRandomPassphrase: () => string; readonly passphrase: string; }`usePassphraseAuth` hook provides a `JazzAuth` object for passphrase authentication.usePassphraseAuth } from "jazz-tools/expo"; import {import englishWordlistenglishWordlist } from "./wordlist"; functionJazzAuthentication({function JazzAuthentication({ children }: { children: ReactNode; }): string | number | bigint | boolean | Iterable<React.ReactNode> | Promise<AwaitedReactNode> | React.JSX.Element | null | undefinedchildren: React.ReactNodechildren }: {children: React.ReactNodechildren:type ReactNode = string | number | bigint | boolean | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | React.ReactPortal | Promise<...> | null | undefinedRepresents all of the things React can render. Where {@link ReactElement } only represents JSX, `ReactNode` represents everything that can be rendered.ReactNode }) { constauth =const auth: { readonly state: "anonymous" | "signedIn"; readonly logIn: (passphrase: string) => Promise<void>; readonly signUp: (name?: string) => Promise<string>; readonly registerNewAccount: (passphrase: string, name: string) => Promise<string>; readonly generateRandomPassphrase: () => string; readonly passphrase: string; }function usePassphraseAuth({ wordlist }: { wordlist: string[]; }): { readonly state: "anonymous" | "signedIn"; readonly logIn: (passphrase: string) => Promise<void>; readonly signUp: (name?: string) => Promise<string>; readonly registerNewAccount: (passphrase: string, name: string) => Promise<string>; readonly generateRandomPassphrase: () => string; readonly passphrase: string; }`usePassphraseAuth` hook provides a `JazzAuth` object for passphrase authentication.usePassphraseAuth({wordlist: string[]wordlist:import englishWordlistenglishWordlist, }); // If the user is already signed in, render the App if (auth.const auth: { readonly state: "anonymous" | "signedIn"; readonly logIn: (passphrase: string) => Promise<void>; readonly signUp: (name?: string) => Promise<string>; readonly registerNewAccount: (passphrase: string, name: string) => Promise<string>; readonly generateRandomPassphrase: () => string; readonly passphrase: string; }state: "anonymous" | "signedIn"state === "signedIn") { returnchildren: React.ReactNodechildren } // Otherwise, show a sign-in screen return <SignInScreenfunction SignInScreen({ auth }: { auth: any; }): nullauth: anyauth={auth} />; } functionconst auth: { readonly state: "anonymous" | "signedIn"; readonly logIn: (passphrase: string) => Promise<void>; readonly signUp: (name?: string) => Promise<string>; readonly registerNewAccount: (passphrase: string, name: string) => Promise<string>; readonly generateRandomPassphrase: () => string; readonly passphrase: string; }AuthenticatedProvider({function AuthenticatedProvider({ children }: { children: ReactNode; }): React.JSX.Elementchildren: React.ReactNodechildren }: {children: React.ReactNodechildren:type ReactNode = string | number | bigint | boolean | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | React.ReactPortal | Promise<...> | null | undefinedRepresents all of the things React can render. Where {@link ReactElement } only represents JSX, `ReactNode` represents everything that can be rendered.ReactNode }) { return ( <function JazzExpoProvider<S extends (AccountClass<Account> & CoValueFromRaw<Account>) | CoreAccountSchema>(props: JazzProviderProps<S>): JSX.ElementJazzExpoProvidersync: SyncConfigsync={{peer: "wss://cloud.jazz.tools/?key=you@example.com"peer: `wss://cloud.jazz.tools/?key=${const apiKey: "you@example.com"Use your email as a temporary key, or get a free API Key at dashboard.jazz.tools for higher limits.apiKey}` }} > <JazzAuthentication> {function JazzAuthentication({ children }: { children: ReactNode; }): string | number | bigint | boolean | Iterable<React.ReactNode> | Promise<AwaitedReactNode> | React.JSX.Element | null | undefinedchildren: React.ReactNodechildren} </JazzAuthentication> </function JazzAuthentication({ children }: { children: ReactNode; }): string | number | bigint | boolean | Iterable<React.ReactNode> | Promise<AwaitedReactNode> | React.JSX.Element | null | undefinedfunction JazzExpoProvider<S extends (AccountClass<Account> & CoValueFromRaw<Account>) | CoreAccountSchema>(props: JazzProviderProps<S>): JSX.ElementJazzExpoProvider> ); }
For a complete example, see the Expo Chat Demo.
Local Persistence
Jazz for Expo includes built-in local persistence using SQLite. Following Expo's best practices, the Expo implementation uses:
- Database Storage:
expo-sqlite- Expo's official SQLite module - Key-Value Storage:
expo-secure-store- Expo's secure storage system
Local persistence is enabled by default with no additional configuration required. Your data will automatically persist across app restarts.
Quick Crypto
For accelerated crypto operations, you can use the RNQuickCrypto crypto provider.
To use it, install the following Packages:
pnpm add react-native-quick-crypto@1.0.0-beta.18 react-native-nitro-modules react-native-fast-encoder
Then add the following to your JazzExpoProvider:
import {function JazzExpoProvider<S extends (AccountClass<Account> & CoValueFromRaw<Account>) | CoreAccountSchema>(props: JazzProviderProps<S>): JSX.ElementJazzExpoProvider } from "jazz-tools/expo"; import {import RNQuickCryptoRNQuickCrypto } from "jazz-tools/expo/crypto"; functionMyJazzProvider({function MyJazzProvider({ children }: { children: ReactNode; }): React.JSX.Elementchildren: React.ReactNodechildren }: {children: React.ReactNodechildren:type ReactNode = string | number | bigint | boolean | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | React.ReactPortal | Promise<...> | null | undefinedRepresents all of the things React can render. Where {@link ReactElement } only represents JSX, `ReactNode` represents everything that can be rendered.ReactNode }) { return ( <function JazzExpoProvider<S extends (AccountClass<Account> & CoValueFromRaw<Account>) | CoreAccountSchema>(props: JazzProviderProps<S>): JSX.ElementJazzExpoProvidersync: SyncConfigsync={{peer: "wss://cloud.jazz.tools/?key=your-api-key"peer: "wss://cloud.jazz.tools/?key=your-api-key" }}CryptoProvider?: anyCryptoProvider={import RNQuickCryptoRNQuickCrypto} > {children: React.ReactNodechildren} </function JazzExpoProvider<S extends (AccountClass<Account> & CoValueFromRaw<Account>) | CoreAccountSchema>(props: JazzProviderProps<S>): JSX.ElementJazzExpoProvider> ); }
For configuration, use the RNQC Expo config plugin:
// app.json { "expo": { "plugins": [ [ "react-native-quick-crypto", { "sodiumEnabled": true } ] ] } }