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>) | AnyAccountSchema>(props: JazzProviderProps<S>): JSX.ElementJazzExpoProvider } from "jazz-tools/expo";
import { import MyAppAccountMyAppAccount } from "./schema";

export function 
function MyJazzProvider({ children }: {
    children: React.ReactNode;
}): React.JSX.Element
MyJazzProvider
({ children: 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 | undefined
Represents all of the things React can render. Where {@link ReactElement } only represents JSX, `ReactNode` represents everything that can be rendered.
@see{@link https://react-typescript-cheatsheet.netlify.app/docs/react-types/reactnode/ React TypeScript Cheatsheet}@example```tsx // Typing children type Props = { children: ReactNode } const Component = ({ children }: Props) => <div>{children}</div> <Component>hello</Component> ```@example```tsx // Typing a custom element type Props = { customElement: ReactNode } const Component = ({ customElement }: Props) => <div>{customElement}</div> <Component customElement={<div>hello</div>} /> ```
ReactNode
}) {
return ( <function JazzExpoProvider<S extends (AccountClass<Account> & CoValueFromRaw<Account>) | AnyAccountSchema>(props: JazzProviderProps<S>): JSX.ElementJazzExpoProvider sync: SyncConfigsync={{ peer: "wss://cloud.jazz.tools/?key=you@example.com"peer: "wss://cloud.jazz.tools/?key=you@example.com" }} AccountSchema?: anyAccountSchema={import MyAppAccountMyAppAccount} > {children: React.ReactNodechildren} </function JazzExpoProvider<S extends (AccountClass<Account> & CoValueFromRaw<Account>) | AnyAccountSchema>(props: JazzProviderProps<S>): JSX.ElementJazzExpoProvider> ); }

Provider Options

  • kvStore
    • ExpoSecureStoreAdapter (default)
  • AccountSchema
    • Account (default)
  • CryptoProvider
    • PureJSCrypto (default) - Pure JavaScript crypto provider
    • RNQuickCrypto - 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:

  1. Import the wordlist for generating recovery phrases
  2. Use the usePassphraseAuth hook to handle authentication
  3. Create simple registration and sign-in screens
// Example with PassphraseAuth
import { function JazzExpoProvider<S extends (AccountClass<Account> & CoValueFromRaw<Account>) | AnyAccountSchema>(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.
@example```ts const auth = usePassphraseAuth({ appName, appHostname, wordlist }); ```@categoryAuth Providers
usePassphraseAuth
} from "jazz-tools/expo";
import { import englishWordlistenglishWordlist } from "./wordlist"; function
function JazzAuthentication({ children }: {
    children: ReactNode;
}): string | number | bigint | boolean | Iterable<React.ReactNode> | Promise<AwaitedReactNode> | React.JSX.Element | null | undefined
JazzAuthentication
({ children: 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 | undefined
Represents all of the things React can render. Where {@link ReactElement } only represents JSX, `ReactNode` represents everything that can be rendered.
@see{@link https://react-typescript-cheatsheet.netlify.app/docs/react-types/reactnode/ React TypeScript Cheatsheet}@example```tsx // Typing children type Props = { children: ReactNode } const Component = ({ children }: Props) => <div>{children}</div> <Component>hello</Component> ```@example```tsx // Typing a custom element type Props = { customElement: ReactNode } const Component = ({ customElement }: Props) => <div>{customElement}</div> <Component customElement={<div>hello</div>} /> ```
ReactNode
}) {
const
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;
}
auth
=
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.
@example```ts const auth = usePassphraseAuth({ appName, appHostname, wordlist }); ```@categoryAuth Providers
usePassphraseAuth
({
wordlist: string[]wordlist: import englishWordlistenglishWordlist, }); // If the user is already signed in, render the App if (
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;
}
auth
.state: "anonymous" | "signedIn"state === "signedIn") {
return children: React.ReactNodechildren } // Otherwise, show a sign-in screen return <
function SignInScreen({ auth }: {
    auth: any;
}): null
SignInScreen
auth: anyauth={
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;
}
auth
} />;
} function
function AuthenticatedProvider({ children }: {
    children: ReactNode;
}): React.JSX.Element
AuthenticatedProvider
({ children: 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 | undefined
Represents all of the things React can render. Where {@link ReactElement } only represents JSX, `ReactNode` represents everything that can be rendered.
@see{@link https://react-typescript-cheatsheet.netlify.app/docs/react-types/reactnode/ React TypeScript Cheatsheet}@example```tsx // Typing children type Props = { children: ReactNode } const Component = ({ children }: Props) => <div>{children}</div> <Component>hello</Component> ```@example```tsx // Typing a custom element type Props = { customElement: ReactNode } const Component = ({ customElement }: Props) => <div>{customElement}</div> <Component customElement={<div>hello</div>} /> ```
ReactNode
}) {
return ( <function JazzExpoProvider<S extends (AccountClass<Account> & CoValueFromRaw<Account>) | AnyAccountSchema>(props: JazzProviderProps<S>): JSX.ElementJazzExpoProvider sync: SyncConfigsync={{ peer: "wss://cloud.jazz.tools/?key=your-api-key"peer: "wss://cloud.jazz.tools/?key=your-api-key" }} > <
function JazzAuthentication({ children }: {
    children: ReactNode;
}): string | number | bigint | boolean | Iterable<React.ReactNode> | Promise<AwaitedReactNode> | React.JSX.Element | null | undefined
JazzAuthentication
>
{children: React.ReactNodechildren} </
function JazzAuthentication({ children }: {
    children: ReactNode;
}): string | number | bigint | boolean | Iterable<React.ReactNode> | Promise<AwaitedReactNode> | React.JSX.Element | null | undefined
JazzAuthentication
>
</function JazzExpoProvider<S extends (AccountClass<Account> & CoValueFromRaw<Account>) | AnyAccountSchema>(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

Then add the following to your JazzExpoProvider:

import { function JazzExpoProvider<S extends (AccountClass<Account> & CoValueFromRaw<Account>) | AnyAccountSchema>(props: JazzProviderProps<S>): JSX.ElementJazzExpoProvider } from "jazz-tools/expo";
import { var RNQuickCrypto: typeof _RNQuickCryptoRNQuickCrypto } from "jazz-tools/expo/crypto";

function 
function MyJazzProvider({ children }: {
    children: ReactNode;
}): React.JSX.Element
MyJazzProvider
({ children: 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 | undefined
Represents all of the things React can render. Where {@link ReactElement } only represents JSX, `ReactNode` represents everything that can be rendered.
@see{@link https://react-typescript-cheatsheet.netlify.app/docs/react-types/reactnode/ React TypeScript Cheatsheet}@example```tsx // Typing children type Props = { children: ReactNode } const Component = ({ children }: Props) => <div>{children}</div> <Component>hello</Component> ```@example```tsx // Typing a custom element type Props = { customElement: ReactNode } const Component = ({ customElement }: Props) => <div>{customElement}</div> <Component customElement={<div>hello</div>} /> ```
ReactNode
}) {
return ( <function JazzExpoProvider<S extends (AccountClass<Account> & CoValueFromRaw<Account>) | AnyAccountSchema>(props: JazzProviderProps<S>): JSX.ElementJazzExpoProvider sync: SyncConfigsync={{ peer: "wss://cloud.jazz.tools/?key=your-api-key"peer: "wss://cloud.jazz.tools/?key=your-api-key" }} CryptoProvider?: typeof PureJSCrypto | typeof RNQuickCrypto | undefinedCryptoProvider={var RNQuickCrypto: typeof _RNQuickCryptoRNQuickCrypto} > {children: React.ReactNodechildren} </function JazzExpoProvider<S extends (AccountClass<Account> & CoValueFromRaw<Account>) | AnyAccountSchema>(props: JazzProviderProps<S>): JSX.ElementJazzExpoProvider> ); }

For configuration, use the RNQC Expo config plugin:

// app.json
{
  "expo": {
    "plugins": [
      [
        "react-native-quick-crypto",
        {
          "sodiumEnabled": true
        }
      ]
    ]
  }
}