Flexible Sync - React Native SDK
On this page
Overview
Flexible Sync uses subscriptions and permissions to determine which data to sync with your Realm app.
To use Flexible Sync in a React Native client:
- Configure Flexible Sync on the backend.
- Initialize the app
- Authenticate a user in your client project.
- Open the synced Realm with a Flexible Sync configuration
- Add subscriptions to the client application
You can add, update, and remove query subscriptions to determine which data syncs to the client device.
Flexible Sync is currently in preview. We encourage you to try out the feature and give feedback, but please be aware that:
- Configuration details may change.
- SDK API implementation details may change.
We do not recommend using Flexible Sync in production applications while it is still in preview.
Enabling Flexible Sync in Your Realm Application requires the following:
- A non-sharded MongoDB Atlas cluster running MongoDB 5.0 or greater
- A Realm app without Partition-Based Sync enabled. While Flexible Sync is in preview, you cannot use Flexible Sync & Partition-Based Sync in the same Realm app.
In addition to the requirements above, you must use Realm JS version 10.12.0 or greater in order to use Flexible Sync in your React Native application.
Subscribe to Queryable Fields
When configuring Flexible Sync on the backend, you specify which fields
your client application can query. In the client application, use the
Subscriptions
API to manage a set of subscriptions to specific queries on
queryable fields.
You can:
- Get a list of all subscriptions
- Add subscriptions
- Check subscription state
- Update a subscription with a new query
- Remove individual subscriptions or all subscriptions of a type
When data matches the subscription and has appropriate permissions, it syncs between devices and the backend application.
A Realm subscription in JavaScript has:
- A created and updated date
- A name
- An object type
- A query string
You can specify a string name for your subscription. If you do not give your subscription a name, the name is set to null.
When you create a subscription, Realm looks for data matching a query on a specific object type. In your Flexible Sync subscriptions, you can have subscriptions on several different object types or several queries on the same object type.
In the following example, queries are created to subscribe to:
- A filtered list of completed tasks that have taken over 120
progressMinutes
- A filtered list of completed tasks
Notice that queries that you subscribe to using Flexible Sync are syntactically the same as querying a realm and that the queries below will create an overlapping result set.
const tasks = realm.objects("Task"); const longRunningTasks = tasks.filtered( 'status == "completed" && progressMinutes > 120' ); const bensTasks = tasks.filtered('owner == "Ben"');
You must add both an object and its linked object to the subscription set to see a linked object.
If your subscription results contain an object with a property that links to an object not contained in the results, the link appears to be null. There is no way to distinguish whether that property's value is legitimately null, or whether the object it links to exists but is out of view of the query subscription.
Get Subscriptions
When using a flexible synced realm, you can access a SubscriptionSet
, a
collection of subscriptions, through the realm.subscriptions property.
// get the SubscriptionSet for the realm const subscriptions = realm.subscriptions;
You can use this SubscriptionSet
to add queries to the list of subscriptions and
update existing subscriptions, as shown in the examples below.
Add a Query to the List Of Subscriptions
Compose queries to add to your Flexible Sync subscriptions using the query engine:
const tasks = realm.objects("Task"); const longRunningTasks = tasks.filtered( 'status == "completed" && progressMinutes > 120' ); const bensTasks = tasks.filtered('owner == "Ben"');
You cannot use all queries with Flexible Sync subscriptions. Refer to the Flexible Sync RQL Limitations documentation for information on which query types are not supported.
Add queries to your subscriptions list to sync the query's data. To do so, perform the following:
- Create a transaction by passing a callback function to the
SubscriptionSet.update()
method of your
SubscriptionSet
. The callback function provides a MutableSubscriptionSet as an argument. - Within the callback function, call the
add()
method on the
MutableSubscriptionSet
to add a query to the subscription.
The following example shows how to subscribe to the queries created above.
await realm.subscriptions.update((mutableSubs) => { mutableSubs.add(longRunningTasks, { name: "longRunningTasksSubscription", }); mutableSubs.add(bensTasks); mutableSubs.add(realm.objects("Team"), { name: "teamsSubscription", throwOnUpdate: true, }); });
The add()
method on the MutableSubscriptionSet
takes a query
and a
SubscriptionOptions object.
The subscription options include:
- a
name
string field - a
throwOnUpdate
boolean field.
If throwOnUpdate
is false or undefined, adding a subscription with an
existing name will replace the existing query with the new query. However, if
you set throwOnUpdate
to true, adding a subscription with an existing name
but a different query throws an exception.
Check the Status of Subscriptions
You can check the subscription state to see if the server has acknowledged the subscription and the device has downloaded the data locally.
You can use subscription state to:
- Trigger error handling
- Show if the transaction is pending or has completed
- Find out when a subscription set is superseded, and you should obtain a new instance of the subscription set to write a subscription change
To the status of subscriptions, log the value of the subscription's state.
console.log(realm.subscriptions.state); // log the subscription state
Update Subscriptions with a New Query
You can update a named subscription with a new query. To update a subscriptions
query, pass the new query and a subscription option with the name of the
subscription that you want to update to the
MutableSubscriptionSet.add()
method. Like adding a new subscription,
you must update a subscription within a transaction by calling
subscriptions.update()
method.
In the following example, long-running tasks are re-defined to be any tasks that have taken more than 180 minutes.
realm.subscriptions.update((mutableSubs) => { mutableSubs.add(tasks.filtered('status == "completed" && progressMinutes > 180'), { name: "longRunningTasksSubscription", }); });
Attempting to update a subscription that has the
SubscriptionOptions.throwOnUpdate
field set to true, throw an exception.
Remove Subscriptions
To remove subscriptions from the subscription set, you can:
- Remove a single subscription with the given query
- Remove a single subscription with the given name
- Remove all subscriptions on a specific type
- Remove all subscriptions
When you remove a subscription query, the server also removes synced data from the client device.
Remove a Subscription by Query
You can remove a specific subscription by query by executing a transaction on
the subscriptions set. Pass the query to the remove() method on the
MutableSubscriptionSet
within a transaction.
In the following example, the subscription to tasks with an owner named 'Ben' is removed from the subscriptions set.
realm.subscriptions.update((mutableSubs) => { // remove a subscription with a specific query mutableSubs.remove(tasks.filtered('owner == "Ben"')); });
Remove a Subscription by Name
To remove a specific subscription by name, execute a transaction on the
subscriptions set. Within the transaction, pass the name to the
removeByName() method on the
MutableSubscriptionSet
.
realm.subscriptions.update((mutableSubs) => { // remove a subscription with a specific name mutableSubs.removeByName("longRunningTasksSubscription"); });
Remove a Subscription by Reference
If you have a reference to a subscription, you can remove that subscription. To
do so, execute a transaction on the subscriptions set. Within the transaction,
pass the reference variable to the removeSubscription method on the
MutableSubscriptionSet
.
let subscriptionReference; realm.subscriptions.update((mutableSubs) => { subscriptionReference = mutableSubs.add(realm.objects("Task")); }); // later.. realm.subscriptions.removeSubscription(subscriptionReference);
Remove All Subscriptions on an Object Type
To remove all subscriptions on a specific object type, execute a transaction on
the subscriptions set. Within the transaction, pass the object type as a string
to the removeByObjectType method on the
MutableSubscriptionSet
.
realm.subscriptions.update((mutableSubs) => { mutableSubs.removeByObjectType("Team"); });
Remove All Subscriptions
To remove all subscriptions from the subscriptions set, execute a transaction on
the subscriptions set. Call the removeAll() method on the
MutableSubscriptionSet
within the transaction
realm.subscriptions.update((mutableSubs) => { mutableSubs.removeAll(); });