Open synced local database when completely offline

After I authenticate and sync my react native app with my database cluster using MongoDB Realm Sync, I want to open my app completely offline. How can I do that ? It works fine when I open it online. But, when I open it offline, it does not return anything , neither it gives any error.
Below is my code:

 const config = {
      schema: [sessionSchema],
 sync: {
        user,
        partitionValue: 'Test',
      }
} 

 Realm.open(config)
        .then((openedRealm) => {
          if (canceled) {
            openedRealm.close();
            return;
          }
          realmRef.current = openedRealm;
          const syncCampaigns = openedRealm.objects('session');
});
4 Likes

Hi,
I had similar issue regarding using offline only with the iOS SDK. And I found the following solution. Not quite sure what you should use in the React Native SDK, but maybe this can help you anyways.

First time I login in the app I’m using the Realm.OpenAsync() function (after successfully logon), to get data from the server. Once the data is received the user is automatically stored behind the scenes in the keychain by the SDK. When I open the app next time I won’t do a Realm.OpenAsync(). I first look at the Realm.App instance and try to get the user from that by doing app.currentUser. If a user is available then I can use that user to initialize Realm.
See below:

let configuration = AppConfiguration(
			baseURL:  // Custom base URL
			transport: nil, // Custom RLMNetworkTransportProtocol
			localAppName: "AppName",
			localAppVersion: "1.0",
			defaultRequestTimeoutMS: 30000
		)
let app = App(id: "someId", configuration: configuration)

if let user = app.currentUser {
			var config = user.configuration(partitionValue: "SHARED")
			config.objectTypes = kSyncedObjectTypes
			do {
				let realm = try Realm.init(configuration: config, queue: .main)
			}
		} else {
		
        let creds = Credentials.jwt(token: "someToken"

			app.login(credentials: creds) { result in
				switch result {
				case .success(let user):
					var config = user.configuration(partitionValue: "SHARED")
					config.objectTypes = kSyncedObjectTypes
					Realm.asyncOpen(configuration: config, callbackQueue: .main, callback: completion)
				}
			}
		}

The important thing is that you always need the user to create the configuration and to open the Realm db.
So Realm.asyncOpen for the initial load/first time login and from that point you will always need to use Realm.init() from the locally stored user.

Hope this helps,
Sujeevan

1 Like

Do you know how to manage the same situation in React Native SDK. There is no method Realm.init()

I haven’t tried in the React Native SDK, but I think it would something like this:

async function getRealm() {
    const app = new Realm.App("your-app-id");
    if (app.currentUser) {
        // A user had already logged in - open the Realm synchronously
        return new Realm(getConfig(app.currentUser));
    }

    // We don't have a user - login a user and open the realm async
    const user = await app.logIn(Realm.Credentials.anonymous());
    return await Realm.open(getConfig(user));
}

function getConfig(user) {
    return {
        sync: {
            user,
            partitionValue: "my-partition"
        }
    };
}

Maybe you can also look at the discussion following the link: Local Realm open after synchronized on realm cloud - #4 by Ian_Ward

1 Like

yeah, that works. Thank you so much! It solved my problem

Hi @Lukasz_Stachurski, could you please share how you solved it to work off-line? I’ve been having the same problem here with reat-native.

function getConfig(user, appId) {
  return {
    schema: [Account.schema],
    sync: {
      user,
      partitionValue: `${appId}`,
    },
    error: function(session, syncError) {
      console.log('session  ------>', session)
      console.log('syncError  ------>', syncError)
    },
  }
}



async function handleLogin(){
 const user = await app.logIn(credentials)
 const finalUser = await user.functions.getUserData({email})
 await Realm.open(getConfig(user, finalUser._appId))}

const config = {
      // schema: [Account.schema],
      sync: {
        user,
        partitionValue: 'abc-123',
      },
      error: function(session, syncError) {
        console.log('session  ------>', session)
        console.log('syncError  ------>', syncError)
      },
    }
    try {
      const realm = new Realm(config)
      const all = realm.objects('Account')
      console.log('all', all)
    } catch (error) {
      console.log('error', error)
    }

Hi @Lukasz_Stachurski i’m facing the same problem with RN, i already have my app.currentUser but it’s not enought to complete the connection with Realm MongoDB offline, do you have any working offline example that you can share with us ?

Hi, the idea is to not open new connection if you already have user in app.currentUser.
Take a look on a example given by Sujeevan_Kuganesan

I did it but still not working.

Realm.open() only works with connection, if i want to get all data in “Account” wich is a synched collection, how i do it offline?

This is how i did:

const realmRef = useRef(null);
const config = {
        schema: [accountSchema],
        sync: {
          user,
          partitionValue: projectId,
        },
      };
try {
        if (isConnected) {
          Realm.open(config)
            .then((openedRealm) => {
              if (canceled) {
                openedRealm.close();
                return;
              }
              realmRef.current = openedRealm;
        const syncAccount = openedRealm.objects('account');
        setAccount(syncAccount);
            })
            .catch((error) => console.warn('Failed to open realm:', error));
        } else {
          const localRealm = new Realm(config);
          realmRef.current = localRealm;
         const syncAccount = localRealm.objects('account');
         setAccount(syncAccount)l
        }
      } catch (e) {
        console.log('ERROR', e);
      }
3 Likes

I know this is an old thread, but just for the record, Realm caches de user when you log in for the first time.

Sou, you can do something like this (React Native version):

const app = new Realm.App(appConfig);

const credentials = Realm.Credentials.jwt(accessToken);

try {
  // Try to login, but ignore the error to allow continue offline.
  await app.logIn(credentials);
} catch (err) {
  console.warn(err);
}

if (app.currentUser) {
  // Ensure that exists a cached or logged user
  throw new Error('Realm login failed: current user not found');
}

const realm = await Realm.open({
      schema: config.schema,
      schemaVersion: config.schemaVersion,
      sync: {
        user: app.currentUser,
        partitionValue: config.partition,
        ...
      },
    });

// Done!

Docs: https://www.mongodb.com/docs/realm/sdk/node/examples/open-and-close-a-realm/#open-a-synced-realm-while-offline