React Native Installation and Setup

This guide covers setting up Jazz for React Native applications from scratch. If you're using Expo, please refer to the React Native - Expo guide instead. If you just want to get started quickly, you can use our React Native Chat Demo as a starting point.

Jazz supports the New Architecture for React Native.

Tested with:

"react-native": "0.78.22",
"react": "18.3.1" 

Installation

Create a new project

(Skip this step if you already have one)

npx @react-native-community/cli init myjazzapp
cd myjazzapp

If you intend to build for iOS, you can accept the invitation to install CocoaPods. If you decline, or you get an error, you can install it with pod-install.

Install dependencies

# React Native dependencies
npm install @react-native-community/netinfo @bam.tech/react-native-image-resizer

# React Native polyfills
npm i -S @azure/core-asynciterator-polyfill react-native-url-polyfill readable-stream react-native-get-random-values @craftzdog/react-native-buffer @op-engineering/op-sqlite react-native-mmkv

# Jazz dependencies
npm i -S jazz-tools jazz-react-native jazz-react-native-media-images

Note: Hermes has added support for atob and btoa in React Native 0.74. If you are using earlier versions, you may also need to polyfill atob and btoa in your package.json. Packages to try include text-encoding and base-64, and you can drop @bacons/text-decoder.

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:

// metro.config.js
const { const getDefaultConfig: anygetDefaultConfig, const mergeConfig: anymergeConfig } = 
var require: NodeRequire
(id: string) => any
require
('@react-native/metro-config');
const
const config: {
    resolver: {
        sourceExts: string[];
        requireCycleIgnorePatterns: RegExp[];
    };
}
config
= {
resolver: {
    sourceExts: string[];
    requireCycleIgnorePatterns: RegExp[];
}
resolver
: {
sourceExts: string[]sourceExts: ["mjs", "js", "json", "ts", "tsx"], requireCycleIgnorePatterns: RegExp[]requireCycleIgnorePatterns: [/(^|\/|\\)node_modules($|\/|\\)/] } }; var module: NodeModulemodule.NodeJS.Module.exports: anyexports = const mergeConfig: anymergeConfig(const getDefaultConfig: anygetDefaultConfig(var __dirname: string__dirname),
const config: {
    resolver: {
        sourceExts: string[];
        requireCycleIgnorePatterns: RegExp[];
    };
}
config
);

Monorepos

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

// metro.config.js
const const path: anypath = 
var require: NodeRequire
(id: string) => any
require
("path");
const { const makeMetroConfig: anymakeMetroConfig } =
var require: NodeRequire
(id: string) => any
require
("@rnx-kit/metro-config");
const const MetroSymlinksResolver: anyMetroSymlinksResolver =
var require: NodeRequire
(id: string) => any
require
("@rnx-kit/metro-resolver-symlinks");
// Define workspace root const const projectRoot: stringprojectRoot = var __dirname: string__dirname; const const workspaceRoot: anyworkspaceRoot = const path: anypath.resolve(const projectRoot: stringprojectRoot, "../.."); // Add packages paths const
const extraNodeModules: {
    modules: any;
}
extraNodeModules
= {
modules: anymodules: const path: anypath.resolve(const workspaceRoot: anyworkspaceRoot, "node_modules"), }; const const watchFolders: any[]watchFolders = [ const path: anypath.resolve(const workspaceRoot: anyworkspaceRoot, "node_modules"), const path: anypath.resolve(const workspaceRoot: anyworkspaceRoot, "packages"), ]; const const nodeModulesPaths: any[]nodeModulesPaths = [ const path: anypath.resolve(const projectRoot: stringprojectRoot, "node_modules"), const path: anypath.resolve(const workspaceRoot: anyworkspaceRoot, "node_modules"), ]; var module: NodeModulemodule.NodeJS.Module.exports: anyexports = const makeMetroConfig: anymakeMetroConfig({
resolver: {
    resolveRequest: any;
    extraNodeModules: {
        modules: any;
    };
    nodeModulesPaths: any[];
}
resolver
: {
resolveRequest: anyresolveRequest: const MetroSymlinksResolver: anyMetroSymlinksResolver(),
extraNodeModules: {
    modules: any;
}
extraNodeModules
,
nodeModulesPaths: any[]nodeModulesPaths, }, sourceExts: string[]sourceExts: ["mjs", "js", "json", "ts", "tsx"], watchFolders: any[]watchFolders, });

Additional monorepo configuration (for pnpm)

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

Add polyfills

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

// polyfills.js
import { import polyfillGlobalpolyfillGlobal } from 'react-native/Libraries/Utilities/PolyfillFunctions';
import { class BufferBuffer } from "@craftzdog/react-native-buffer";
import polyfillGlobalpolyfillGlobal("Buffer", () => class BufferBuffer); // polyfill Buffer

import { import ReadableStreamReadableStream } from "readable-stream";
import polyfillGlobalpolyfillGlobal("ReadableStream", () => import ReadableStreamReadableStream); // polyfill ReadableStream

import "@azure/core-asynciterator-polyfill"; // polyfill Async Iterator
import "@bacons/text-decoder/install"; // polyfill Text Decoder
import 'react-native-get-random-values'; // polyfill getRandomValues

Update index.js:

// index.js
import { AppRegistry } from 'react-native';
import import AppApp from './App';
import { name as import appNameappName } from './app.json';
import './src/polyfills';

AppRegistry.function AppRegistry.registerComponent(appKey: string, getComponentFunc: ComponentProvider, section?: boolean): stringregisterComponent(import appNameappName, () => import AppApp);

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

// package.json
{
  "main": "index.js",
  ...
}

Authentication

Jazz provides authentication to help users access their data across multiple devices. For details on implementing authentication, check our Authentication Overview guide and see the React Native Chat Demo for a complete example.

Next Steps

Now that you've set up your React Native project for Jazz, you'll need to:

  1. Set up the Jazz Provider - Configure how your app connects to Jazz
  2. Add authentication (optional) - Enable users to access data across devices
  3. Define your schema - See the schema docs for more information
  4. Run your app:
npx react-native run-ios
npx react-native run-android

Verification

Ready to see if everything's working? Let's fire up your app:

npx react-native run-ios
# or
npx react-native run-android

If all goes well, your app should start up without any angry red error screens. Take a quick look at the Metro console too - no Jazz-related errors there means you're all set! If you see your app's UI come up smoothly, you've nailed the installation.

If you run into any issues that aren't covered in the Common Issues section, drop by our Discord for help.

Common Issues

  • Metro bundler errors: If you see errors about missing polyfills, ensure all polyfills are properly imported in your polyfills.js file.
  • iOS build failures: Make sure you've run pod install after adding the dependencies.
  • Android build failures: Ensure your Android SDK and NDK versions are compatible with the native modules.

Install CocoaPods

If you're compiling for iOS, you'll need to install CocoaPods for your project. If you need to install it, we recommend using pod-install:

npx pod-install