React Native

Jazz requires an Expo development build using Expo Prebuild for native code. It is not compatible with Expo Go. Jazz also supports the New Architecture.

Tested with:

"expo": "~51.0.0", "react-native": "~0.74.5", "react": "^18.2.0",

Setup

Create a new project

(skip this step if you already have one)

npx create-expo-app -e with-router-tailwind my-jazz-app cd my-jazz-app npx expo prebuild

Install dependencies

npx expo install expo-linking expo-secure-store expo-file-system @react-native-community/netinfo @bam.tech/react-native-image-resizer @azure/core-asynciterator-polyfill npm i -S react-native-polyfill-globals react-native-url-polyfill web-streams-polyfill@3.2.1 base-64 text-encoding react-native-fetch-api react-native-get-random-values buffer npm i -D @babel/plugin-transform-class-static-block npm i -S jazz-tools jazz-react-native jazz-react-native-media-images

Fix incompatible dependencies

npx expo install --fix

Install Pods

npx pod-install

Configure Metro

Regular repositories

If you are not working within a monorepo, create a new file metro.config.js in the root of your project with the following content:

const { getDefaultConfig } = require("expo/metro-config"); const config = getDefaultConfig(projectRoot); config.resolver.unstable_enablePackageExports = true; // important setting config.resolver.sourceExts = ["mjs", "js", "json", "ts", "tsx"]; config.resolver.requireCycleIgnorePatterns = [/(^|\/|\\)node_modules($|\/|\\)/]; module.exports = config;

If you created the project using the command npx create-expo-app -e with-router-tailwind my-jazz-app, then metro.config.js is already present. In that case, simply add this setting to the existing file:

config.resolver.unstable_enablePackageExports = true

Monorepos

For monorepos, use the following metro.config.js:

const { getDefaultConfig } = require("expo/metro-config"); const { FileStore } = require("metro-cache"); const path = require("path"); // eslint-disable-next-line no-undef const projectRoot = __dirname; const workspaceRoot = path.resolve(projectRoot, "../.."); const config = getDefaultConfig(projectRoot); config.watchFolders = [workspaceRoot]; config.resolver.nodeModulesPaths = [ path.resolve(projectRoot, "node_modules"), path.resolve(workspaceRoot, "node_modules"), ]; config.resolver.sourceExts = ["mjs", "js", "json", "ts", "tsx"]; config.resolver.unstable_enablePackageExports = true; config.resolver.requireCycleIgnorePatterns = [/(^|\/|\\)node_modules($|\/|\\)/]; config.cacheStores = [ new FileStore({ root: path.join(projectRoot, "node_modules", ".cache", "metro"), }), ]; module.exports = config;

Additional monorepo configuration (for pnpm users)

  • Add node-linker=hoisted to the root .npmrc (create this file if it doesn’t exist).
  • Add the following to the root package.json:
"pnpm": { "peerDependencyRules": { "ignoreMissing": [ "@babel/*", "expo-modules-*", "typescript" ] } }

For more information, refer to this Expo monorepo example.

Add polyfills

Create a file polyfills.js at the project root with the following content:

import "react-native-polyfill-globals/auto"; import "@azure/core-asynciterator-polyfill"; import { ReadableStream } from "web-streams-polyfill/ponyfill/es6"; import { polyfillGlobal } from "react-native/Libraries/Utilities/PolyfillFunctions"; import { Buffer } from "buffer"; polyfillGlobal("Buffer", () => Buffer); polyfillGlobal("ReadableStream", () => ReadableStream);

Update index.js based on whether you are using expo-router or not:

If using expo-router

import "./polyfills"; import "expo-router/entry";

Without expo-router

import "./polyfills"; import { registerRootComponent } from "expo"; import App from "./src/App"; registerRootComponent(App);

Lastly, ensure that the "main" field in your package.json points to index.js:

"main": "index.js",

Using Jazz

createJazzRNApp()

Create a file jazz.tsx with the following contents:

import { createJazzRNApp } from "jazz-react-native"; export const Jazz = createJazzRNApp(); export const { useAccount, useCoState, useAcceptInvite } = Jazz;

You can optionally pass a custom kvStore and AccountSchema to createJazzRNApp(), otherwise, it defaults to ExpoSecureStoreAdapter and Account.

Choosing an auth method

Refer to the Jazz + React Native demo projects for implementing authentication:

In the demos, you'll find details on:

  • Using Jazz.Provider with your chosen authentication method
  • Defining a Jazz schema
  • Creating and subscribing to covalues
  • Handling invites

Working with Images

To work with images in Jazz, import the createImage function from jazz-react-native-media-images.

import { createImage } from "jazz-react-native-media-images"; const base64ImageDataURI = "data:image/png;base64,..."; const image = await createImage(base64ImageDataURI, { owner: newPetPost._owner, maxSize: 2048, // optional: specify maximum image size }); someCovalue.image = image;

For a complete implementation, please refer to this demo.

Running your app

npx expo run:ios npx expo run:android