Docs Menu
Docs Home
/ /
Atlas Device SDKs
/ /

Manage a Sync Session - React Native SDK

On this page

  • Prerequisites
  • Access Sync Session
  • Pause or Resume a Sync Session
  • When to Pause a Sync Session
  • Check Upload & Download Progress for a Sync Session
  • Check the Network Connection
  • Multiplex Sync Sessions

When you use Atlas Device Sync, the React Native SDK syncs data with Atlas in the background using a sync session. A sync session starts whenever you open a synced realm.

Before you can manage a sync session, you must perform the following:

  1. Open a synced realm

  2. Add a sync subscription

  3. Wrap components that use the useRealm() hook for a synced realm with the AppProvider, UserProvider, and RealmProvider components. For more information on configuring and opening a synced realm, refer to Open a Synced Realm.

Access a synced realm in a component with the useRealm() hook. Access the sync session with the realm's Realm.syncSession property.

import React, {useEffect} from 'react';
import {Context} from '../RealmConfig';
const {useRealm} = Context;
function AccessSyncSession() {
const realm = useRealm();
async function workWithSyncSession() {
const {syncSession} = realm;
// Do stuff with sync session...
}
// ...
}

Opening a synced realm starts a sync session. You can pause and resume the realm's sync session. If you have more than one open realm, pause does not affect the other realms' sync sessions.

To pause synchronization, use the Realm.syncSession.pause() method. To resume synchronization, use the Realm.syncSession.resume() method.

import React, {useEffect, useState} from 'react';
import {Context} from '../RealmConfig';
const {useRealm} = Context;
function ToggleSyncSession() {
const realm = useRealm();
const [isPaused, setIsPaused] = useState(false);
async function toggleSyncSession() {
if (isPaused) {
await realm.syncSession?.resume();
} else {
await realm.syncSession?.pause();
}
setIsPaused(!isPaused);
}
return (
<Button
title={isPaused ? 'Pause Sync' : 'Unpause Sync'}
onPress={toggleSyncSession}
/>
);
}

For most applications, there is no need to manually pause and resume a sync session. However, there are a few circumstances under which you may want to pause or suspend a sync session:

  • You only want to sync after the user takes a specific action

  • You only want to sync during a certain time of the day

  • You don't want to attempt to sync when there is poor network connectivity

  • You want to explicitly force a sync session to connect

In the case of poor network connectivity, continually trying to establish a network connection can drain the user's device battery.

The case of explicitly forcing a sync session to connect is most commonly related to being offline for some time. The sync client attempts to connect, and upon failure, goes into exponential backoff. After being offline for a long time, the client may not immediately reconnect. Pausing and resuming the sync session explicitly forces the connection.

When you do pause a sync session, keep these things in mind:

  • If the client may be offline longer than the client maximum offline time, the client will be unable to resume syncing and must perform a client reset.

  • Pausing a sync session pauses it in both directions. Changes that your app makes on the device do not sync with the backend, and changes to the data in the backend or on other devices do not sync to the device. There is no way to pause only uploads or pause only downloads.

  • Do not pause a sync session if you want a client to permanently stop syncing with the backend. To permanently stop syncing, copy the contents of the synced realm into a non-synced realm, and use the non-synced realm in the client.

Do not pause sync to stop syncing for indefinite time periods or time ranges in months and years. The functionality is not designed or tested for these use cases. You could encounter a range of issues when using it this way.

To check the upload and download progress for a sync session, add a progress notification using the Realm.syncSession.addProgressNotification() method.

The Realm.syncSession.addProgressNotification() method takes in the following three parameters:

  • A direction parameter. Set to "upload" to register notifications for uploading data. Set to "download" to register notifications for downloading data.

  • A mode parameter. Set to "reportIndefinitely" for the notifications to continue until the callback is unregistered using Realm.syncSession.removeProgressNotification(). Set to "forCurrentlyOutstandingWork" for the notifications to continue until only the currently transferable bytes are synced.

  • A callback function parameter that has the arguments transferred and transferable. transferred is the current number of bytes already transferred. transferable is the total number of bytes already transferred plus the number of bytes pending transfer.

Note

Flexible Sync progress notifications are not yet fully supported. When using Flexible Sync, downloads only report notifications after changes are integrated. Partition-Based Sync provides ongoing notifications as changes progress downloading. Uploads report ongoing progress notifications for both Sync Modes.

The following example registers a callback on the syncSession to listen for upload events indefinitely. The example writes to the realm and then unregisters the syncSession notification callback.

import React, {useEffect, useState} from 'react';
import {SyncedRealmContext} from '../RealmConfig';
const {useRealm} = SyncedRealmContext;
import {Text} from 'react-native';
function CheckUploadProgress() {
const realm = useRealm();
const [uploadProgressPercent, setUploadProgressPercent] = useState(0);
useEffect(() => {
const progressNotificationCallback = (transferred, transferable) => {
// Convert decimal to percent with no decimals
// (e.g. 0.6666... -> 67)
const percentTransferred =
parseFloat((transferred / transferable).toFixed(2)) * 100;
setUploadProgressPercent(percentTransferred);
};
// Listen for changes to connection state
realm.syncSession?.addProgressNotification(
Realm.ProgressDirection.Upload,
Realm.ProgressMode.ReportIndefinitely,
progressNotificationCallback,
);
// Remove the connection listener when component unmounts
return () =>
realm.syncSession?.removeProgressNotification(
progressNotificationCallback,
);
// Run useEffect only when component mounts
}, []);
return <Text>Percent Uploaded: {uploadProgressPercent} %</Text>;
}
import React, {useEffect, useState} from 'react';
import {Context} from '../RealmConfig';
const {useRealm} = Context;
import {Text} from 'react-native';
function CheckUploadProgress() {
const realm = useRealm();
const [uploadProgressPercent, setUploadProgressPercent] = useState(0);
useEffect(() => {
const progressNotificationCallback: Realm.ProgressNotificationCallback = (
transferred,
transferable,
) => {
// Convert decimal to percent with no decimals
// (e.g. 0.6666... -> 67)
const percentTransferred =
parseFloat((transferred / transferable).toFixed(2)) * 100;
setUploadProgressPercent(percentTransferred);
};
// Listen for changes to connection state
realm.syncSession?.addProgressNotification(
Realm.ProgressDirection.Upload,
Realm.ProgressMode.ReportIndefinitely,
progressNotificationCallback,
);
// Remove the connection listener when component unmounts
return () =>
realm.syncSession?.removeProgressNotification(
progressNotificationCallback,
);
// Run useEffect only when component mounts
}, []);
return <Text>Percent Uploaded: {uploadProgressPercent} %</Text>;
}

Realm's offline-first design means that you generally don't need to check the current network connection state since data syncs in the background when a connection is available. That said, the Realm SDK provides methods to get the current state of the network connection to the server.

To check the current state of the connection to the server, call Realm.syncSession.isConnected(). This method returns a boolean that is true if there is a network connection and the sync session is active.

To listen for connection state changes, call Realm.syncSession.addConnectionNotification(), passing a callback function to handle network changes as the argument. To unregister the listener, pass the same callback function to Realm.syncSession.removeConnectionNotification().

import React, {useState, useEffect} from 'react';
import {SyncedRealmContext} from '../RealmConfig';
const {useRealm} = SyncedRealmContext;
import {Text} from 'react-native';
function CheckNetworkConnection() {
const realm = useRealm();
const [isConnected, setIsConnected] = useState(
realm.syncSession?.isConnected(),
);
useEffect(() => {
const connectionNotificationCallback = (newState, oldState) => {
console.log('Current connection state: ' + newState);
console.log('Previous connection state: ' + oldState);
setIsConnected(realm.syncSession?.isConnected());
};
// Listen for changes to connection state
realm.syncSession?.addConnectionNotification(
connectionNotificationCallback,
);
// Remove the connection listener when component unmounts
return () =>
realm.syncSession?.removeConnectionNotification(
connectionNotificationCallback,
);
// Run useEffect only when component mounts
}, []);
return (
<Text>
{isConnected ? 'Connected to Network' : 'Disconnected from Network'}
</Text>
);
}
import React, {useState, useEffect} from 'react';
import {Context} from '../RealmConfig';
const {useRealm} = Context;
import {Text} from 'react-native';
function CheckNetworkConnection() {
const realm = useRealm();
const [isConnected, setIsConnected] = useState(
realm.syncSession?.isConnected(),
);
useEffect(() => {
const connectionNotificationCallback: Realm.ConnectionNotificationCallback =
(newState, oldState) => {
console.log('Current connection state: ' + newState);
console.log('Previous connection state: ' + oldState);
setIsConnected(realm.syncSession?.isConnected());
};
// Listen for changes to connection state
realm.syncSession?.addConnectionNotification(
connectionNotificationCallback,
);
// Remove the connection listener when component unmounts
return () =>
realm.syncSession?.removeConnectionNotification(
connectionNotificationCallback,
);
// Run useEffect only when component mounts
}, []);
return (
<Text>
{isConnected ? 'Connected to Network' : 'Disconnected from Network'}
</Text>
);
}

Enable session multiplexing to consolidate multiple sync sessions of a Realm app. Only use session multiplexing if you see errors about reaching the file descriptor limit, and you know you are using many sync sessions.

To enable session multiplexing, call Realm.App.Sync.enableSessionMultiplexing() with your Realm.App.

import React, {useEffect} from 'react';
import {Context} from '../RealmConfig';
import {AppProvider, UserProvider, useUser, useApp, Realm} from '@realm/react';
function AppWrapper() {
return (
<AppProvider id={APP_ID}>
<UserProvider fallback={<LogIn />}>
<RealmWrapper>
<RestOfApp />
</RealmWrapper>
</UserProvider>
</AppProvider>
);
}
type RealmWrapperProps = {
children: React.ReactNode;
};
function RealmWrapper({children}: RealmWrapperProps) {
const app = useApp();
Realm.App.Sync.enableSessionMultiplexing(app);
return <RealmProvider sync={{flexible: true}}>{children}</RealmProvider>;
}

Back

Manage Flexible Sync Subscriptions

Next

Handle Sync Errors