Upgrade to Jazz 0.13.0 for React Native Expo

Version 0.13.0 introduces a significant architectural change in how Jazz supports React Native applications. We've separated the React Native implementation into two distinct packages to better serve different React Native development approaches:

  1. jazz-expo: Dedicated package for Expo applications
  2. jazz-react-native: Focused package for framework-less React Native applications
  3. jazz-react-native-core: Shared core functionality used by both implementations (probably not imported directly)

This guide focuses on upgrading Expo applications. If you're using framework-less React Native, please see the React Native upgrade guide.

Migration Steps for Expo

  1. Update Dependencies

Remove the old packages and install the new jazz-expo package.

# Remove the old package
npm uninstall jazz-react-native

# Install the new Expo-specific packages
npx expo install expo-sqlite expo-secure-store expo-file-system @react-native-community/netinfo

# Install the new packages
npm install jazz-expo jazz-react-native-media-images
  1. Update Imports

Update your imports to use the new jazz-expo package.

// Before
import { function JazzProvider(props: JazzProviderProps): React.JSX.ElementJazzProvider, 
function useAccount<A extends RegisteredAccount>(): {
    me: A;
    logOut: () => void;
} (+1 overload)
useAccount
,
function useCoState<V extends CoValue, const R extends RefsToResolve<V> = true>(Schema: CoValueClass<V>, id: ID<CoValue> | undefined, options?: {
    resolve?: RefsToResolveStrict<V, R>;
}): Resolved<V, R> | undefined | null
useCoState
} from "jazz-react-native";
// After import { function JazzProvider(props: JazzProviderProps): React.JSX.ElementJazzProvider,
function useAccount<A extends RegisteredAccount>(): {
    me: A;
    logOut: () => void;
} (+1 overload)
useAccount
,
function useCoState<V extends CoValue, const R extends RefsToResolve<V> = true>(Schema: CoValueClass<V>, id: ID<CoValue> | undefined, options?: {
    resolve?: RefsToResolveStrict<V, R>;
}): Resolved<V, R> | undefined | null
useCoState
} from "jazz-expo";
  1. Update Type Declarations

Update your type declarations to use the new jazz-expo package.

// Before
declare module "jazz-react-native" { 
  interface Register {
    Register.Account: MyAppAccountAccount: type MyAppAccount = /*unresolved*/ anyMyAppAccount;
  }
}

// After
declare module "jazz-expo" { 
  interface Register {
    Register.Account: MyAppAccountAccount: type MyAppAccount = /*unresolved*/ anyMyAppAccount;
  }
}

Clerk Authentication

Clerk authentication has been moved inside the jazz-expo package. This is a breaking change that requires updating both your imports and providers.

If you're using Clerk auth in your Expo application, you'll need to:

// Before
import { import JazzProviderWithClerkJazzProviderWithClerk } from "jazz-react-native-clerk"; 

// After
import { 
const JazzProviderWithClerk: (props: {
    clerk: MinimalClerkClient;
} & JazzProviderProps) => JSX.Element | null
JazzProviderWithClerk
} from "jazz-expo/auth/clerk";

Since Clerk only supports Expo applications, this consolidation makes sense and simplifies your dependency structure. You'll need to completely remove the jazz-react-native-clerk package from your dependencies and use the Clerk functionality that's now built into jazz-expo.

Storage Adapter Changes

The jazz-expo package now uses:

  • ExpoSQLiteAdapter for database storage (using expo-sqlite)
  • ExpoSecureStoreAdapter for key-value storage (using expo-secure-store)

These are now the default storage adapters in the JazzProvider for Expo applications, so you don't need to specify them explicitly.

Example Provider Setup

import { function JazzProvider(props: JazzProviderProps): React.JSX.ElementJazzProvider } from "jazz-react-native"; 
import { function JazzProvider(props: JazzProviderProps): React.JSX.ElementJazzProvider } from "jazz-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 | boolean | React.ReactElement<any, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | React.ReactPortal | 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 JazzProvider(props: JazzProviderProps): React.JSX.ElementJazzProvider sync: SyncConfigsync={{ peer: "wss://cloud.jazz.tools/?key=you@example.com"peer: "wss://cloud.jazz.tools/?key=you@example.com" }} AccountSchema?: AccountClass<MyAppAccount> | undefinedAccountSchema={import MyAppAccountMyAppAccount} > {children: React.ReactNodechildren} </function JazzProvider(props: JazzProviderProps): React.JSX.ElementJazzProvider> ); } // Register the Account schema declare module "jazz-react-native" { interface Register { Register.Account: MyAppAccountAccount: import MyAppAccountMyAppAccount; } } declare module "jazz-expo" { interface Register { Register.Account: MyAppAccountAccount: import MyAppAccountMyAppAccount; } }

New Architecture Support

The jazz-expo implementation supports the Expo New Architecture.

For More Information

For detailed setup instructions, refer to the React Native Expo Setup Guide