Docs Menu
Docs Home
/ /
Atlas Device SDKs
/ /

Configure a Synced Realm - React Native SDK

On this page

  • Prerequisites
  • Configure a Synced Realm
  • AppProvider
  • UserProvider
  • RealmProvider
  • Open Synced Realm at Specific Path
  • Access a Synced Realm While Offline
  • Access Immediately with Background Sync
  • Access After Timeout with Background Sync
  • @realm/react Providers and Hooks

You can configure a realm to automatically synchronize data between many devices that each have their own local copy of the data.

For more information about synced realms, including directions on how to set up sync in an App Services App, refer to Atlas Device Sync Overview.

For more information about different realm configurations, refer to Configure a Realm.

Before you configure a realm with Flexible Sync in a React Native application:

  1. Enable Flexible Sync on the backend. You must configure Flexible Sync in the backend before you can use it with your client application.

  2. Initialize the App client.

  3. Authenticate a user in your client project.

Configure a synced realm using the providers from @realm/react.

By default, Realm syncs all data from the server before returning anything. If you want to sync data in the background, read Configure a Synced Realm While Offline.

To configure a synced realm:

  1. Import providers from @realm/react.

  2. Configure AppProvider.

  3. Configure UserProvider and nest it within AppProvider.

  4. Configure RealmProvider for sync and nest it within UserProvider. You must set up a sync subscription. The example below uses an initial subscription, but you can also set up subscriptions in RealmProvider child components.

This is how you nest providers:

import React from 'react';
import {AppProvider, UserProvider, RealmProvider} from '@realm/react';
function AppWrapperSync() {
return (
<AppProvider id={APP_ID}>
<UserProvider fallback={LogIn}>
<RealmProvider
schema={[YourObjectModel]}
sync={{
flexible: true,
initialSubscriptions: {
update(subs, realm) {
subs.add(realm.objects(YourObjectModel));
},
},
}}>
<RestOfApp />
</RealmProvider>
</UserProvider>
</AppProvider>
);
}

Note

Partition-Based Sync

This page covers Flexible Sync realms. Flexible Sync is the preferred mode for new apps that use Atlas Device Sync. For information about realms using the older Partition-Based Sync, refer to Partition-Based Sync.

The @realm/react AppProvider gives you access to an instance of your App Services App.

To set up your App client, pass the App ID string to the id prop of AppProvider. Wrap any components that need to access the App with the AppProvider.

import React from 'react';
import {AppProvider} from '@realm/react';
function AppWrapper() {
return (
<View>
<AppProvider id={APP_ID}>
<MyApp />
</AppProvider>
</View>
);
}

You can find more information about AppProvider on the Connect To Atlas App Services page.

UserProvider gives you access to a Realm user. A UserProvider is required for an app to use the hooks.

First, you need to configure user authentication with AppProvider and UserProvider. Then, work with authentication using the useApp() and useUser() hooks.

To set up user authentication:

  1. Wrap all components you want to use with App Services in an AppProvider.

  2. Inside of AppProvider, wrap all components that need access to an authenticated user with a UserProvider.

  3. In UserProvider, include a fallback prop with another component that logs a user in. The app renders this component if there is no authenticated user.

  4. In the component passed to the UserProvider.fallback prop, authenticate a user with Realm.App.logIn(), which you can access with the useApp() hook.

Components wrapped by UserProvider only render if your app has an authenticated user. These components can access the authenticated user with the useUser() hook.

import React from 'react';
import {useApp, UserProvider, AppProvider} from '@realm/react';
import {Button} from 'react-native';
function AppWrapper() {
return (
<AppProvider id={APP_ID}>
{/* If there is no authenticated user,
the app mounts the `fallback` component.
Once the user successfully authenticates,
the app unmounts the component in the
`UserProvider.fallback` prop
(the `LogIn` component in this example). */}
<UserProvider fallback={LogIn}>
{/* Components with access to the user.
These components only mount
if there's an authenticated user.*/}
<RestOfApp />
</UserProvider>
</AppProvider>
);
}
function LogIn() {
const app = useApp();
// This example uses anonymous authentication.
// However, you can use any authentication provider
// to log a user in with this pattern.
async function logInUser() {
await app.logIn(Realm.Credentials.anonymous());
}
return (
<Button
title='Log In'
onPress={logInUser}
/>
);
}

You can find more information about UserProvider on the Authenticate Users page.

RealmProvider is a wrapper that exposes a realm to its child components. You configure your realm by passing props to RealmProvider.

When RealmProvider is rendered, it opens the realm. This means that the child components can't access the realm if rendering fails.

To configure a synced realm:

  1. Import providers from @realm/react.

  2. Configure AppProvider.

  3. Configure UserProvider and nest it within AppProvider.

  4. Pass your object models to RealmProvider's schema prop.

  5. Create a FlexibleSyncConfiguration object.

  6. Pass your SyncConfiguration object to the sync prop or add the object in-line.

  7. Set up initial subscriptions or create a new subscription in RealmProvider child components.

  8. Add other Configuration object properties as props to RealmProvider to further configure your realm.

import React from 'react';
import {AppProvider, UserProvider, RealmProvider} from '@realm/react';
function AppWrapperSync() {
return (
<AppProvider id={APP_ID}>
<UserProvider fallback={LogIn}>
<RealmProvider
schema={[YourObjectModel]}
sync={{
flexible: true,
initialSubscriptions: {
update(subs, realm) {
subs.add(realm.objects(YourObjectModel));
},
},
}}>
<RestOfApp />
</RealmProvider>
</UserProvider>
</AppProvider>
);
}

For more information about configuring and using RealmProvider, check out the Configure a Realm page.

You can configure RealmProvider by setting props that match the properties of a Configuration object. You can also set fallback and realmRef props.

  • realmRef
    Used with useRef to expose the configured realm to processes outside of RealmProvider. This can be useful for things like a client reset fallback.
  • fallback
    Rendered while waiting for the realm to open. Local realms usually open fast enough that the fallback prop isn't needed.

New in version realm@11.6.0.

Using AppConfiguration.baseFilePath, and Realm.BaseConfiguration.path, you can control where Realm and metadata files are stored on client devices.

To do so, set AppProvider.baseFilePath. If baseFilePath is not set, the current work directory is used. You can also set RealmProvider.sync.path for more control.

import React from 'react';
import {AppProvider, UserProvider, RealmProvider} from '@realm/react';
function AppWrapperSync({customBaseFilePath}) {
return (
<AppProvider id={APP_ID} baseFilePath={customBaseFilePath}>
<UserProvider fallback={LogIn}>
<RealmProvider
path={customRealmPath}
schema={[Profile]}
sync={{
flexible: true,
}}>
<RestOfApp />
</RealmProvider>
</UserProvider>
</AppProvider>
);
}
import React from 'react';
import {AppProvider, UserProvider, RealmProvider} from '@realm/react';
type AppWrapperSyncProps = {
customBaseFilePath: string;
};
function AppWrapperSync({customBaseFilePath}: AppWrapperSyncProps) {
return (
<AppProvider id={APP_ID} baseFilePath={customBaseFilePath}>
<UserProvider fallback={LogIn}>
<RealmProvider
path={customRealmPath}
schema={[Profile]}
sync={{
flexible: true,
}}>
<RestOfApp />
</RealmProvider>
</UserProvider>
</AppProvider>
);
}

If baseFilePath is set, metadata is always stored in <baseFilePath>/mongodb-realm/. If baseFilePath isn't set, then metadata is stored in <Realm.defaultPath>/mongodb-realm.

Where, exactly, your Realm file is stored can vary depending on how you set Realm.BaseConfiguration.path:

  • Realm.Configuration.path is not set and baseFilePath is set. Your Realm file is stored at baseFilePath.

  • Realm.Configuation.path is set to a relative path. Your Realm file is stored relative to baseFilePath.

  • Realm.Configuration.path is an absolute path. Your Realm file is stored at Realm.Configuration.path.

The following subsections show how to use background synchronization to access a realm while offline. To do this, use a cached user and an OpenRealmBehaviorConfiguration object.

Within RealmProvider's sync configuration, set the optional newRealmFileBehavior and existingRealmFileBehavior fields to your OpenRealmBehaviorConfiguration object to enable background synchronization.

You can open a realm immediately with background sync or after a timeout.

Note

Initial login requires a network connection

When a user signs up for your app, or logs in for the first time with an existing account on a client, the client must have a network connection. Checking for cached user credentials lets you open a realm offline, but only if the user has previously logged in while online.

You may want to sync changes in the background to display partial data to the user while the synced realm downloads data from the server, preventing the user experience from being blocked. We recommend syncing changes in the background for applications in which the user's device may go offline. To sync changes in the background, open a synced realm synchronously.

import React from 'react';
import {AppProvider, UserProvider, RealmProvider} from '@realm/react';
function AppWrapperOfflineSync() {
const realmAccessBehavior = {
type: 'openImmediately',
};
return (
<AppProvider id={APP_ID}>
<UserProvider fallback={LogIn}>
<RealmProvider
schema={[Profile]}
sync={{
flexible: true,
newRealmFileBehavior: realmAccessBehavior,
existingRealmFileBehavior: realmAccessBehavior,
}}>
<RestOfApp />
</RealmProvider>
</UserProvider>
</AppProvider>
);
}
import React from 'react';
import {AppProvider, UserProvider, RealmProvider} from '@realm/react';
function AppWrapperOfflineSync() {
const realmAccessBehavior: Realm.OpenRealmBehaviorConfiguration = {
type: Realm.OpenRealmBehaviorType.OpenImmediately,
};
return (
<AppProvider id={APP_ID}>
<UserProvider fallback={LogIn}>
<RealmProvider
schema={[Profile]}
sync={{
flexible: true,
newRealmFileBehavior: realmAccessBehavior,
existingRealmFileBehavior: realmAccessBehavior,
}}>
<RestOfApp />
</RealmProvider>
</UserProvider>
</AppProvider>
);
}

If you want to sync data but you're in an environment where it's uncertain if the user has an Internet connection, specify a timeOut. This automatically opens the realm when either:

  • the timeout period elapses.

  • the realm has completely downloaded.

If the realm doesn't finish downloading before the timeout, the initial Sync continues in the background.

import React from 'react';
import {AppProvider, UserProvider, RealmProvider} from '@realm/react';
function AppWrapperTimeoutSync() {
const realmAccessBehavior = {
type: 'downloadBeforeOpen',
timeOutBehavior: 'openLocalRealm',
timeOut: 1000,
};
return (
<AppProvider id={APP_ID}>
<UserProvider fallback={LogIn}>
<RealmProvider
schema={[Profile]}
sync={{
flexible: true,
newRealmFileBehavior: realmAccessBehavior,
existingRealmFileBehavior: realmAccessBehavior,
}}>
<RestOfApp />
</RealmProvider>
</UserProvider>
</AppProvider>
);
}
import React from 'react';
import {AppProvider, UserProvider, RealmProvider} from '@realm/react';
function AppWrapperTimeoutSync() {
const realmAccessBehavior: Realm.OpenRealmBehaviorConfiguration = {
type: 'downloadBeforeOpen',
timeOutBehavior: 'openLocalRealm',
timeOut: 1000,
};
return (
<AppProvider id={APP_ID}>
<UserProvider fallback={LogIn}>
<RealmProvider
schema={[Profile]}
sync={{
flexible: true,
newRealmFileBehavior: realmAccessBehavior,
existingRealmFileBehavior: realmAccessBehavior,
}}>
<RestOfApp />
</RealmProvider>
</UserProvider>
</AppProvider>
);
}

@realm/react has Context Providers and hooks that simplify working with your synced realm and its data. Refer to each Provider's page to learn about them and their hooks.

Back

Sync Data