useQuery for another collection in SyncTutorial

Hi I’m newbie to realm.
I’m trying to adapt the SyncTutorial for Device Sync in mongodb Atlas using React Native
By default the demo collection created is ‘Item’.

Next, relevant code:

AnimalSchema:

//AnimalSchema.tsx
import Realm, {BSON} from 'realm';

export class Animal extends Realm.Object{
  _id!: BSON.ObjectId;
  _owner!: string;
  name!: string;
  sound!: string;

  static schema: Realm.ObjectSchema = {
    name: 'Animal',
    primaryKey: '_id',
    properties: {
      _id: {type: 'objectId', default: () => new BSON.ObjectId()},
      _owner: 'string',
      name: 'string',
      sound: 'string',
    },
  };
};

App:

//App.tsx
import React from 'react';
import {SafeAreaProvider} from 'react-native-safe-area-context';
import {Text, View} from 'react-native';
import {NavigationContainer} from '@react-navigation/native';
import {createStackNavigator} from '@react-navigation/stack';

import {dataExplorerLink} from '../atlasConfig.json';
import {LogoutButton} from './LogoutButton';
import {ItemListView} from './ItemListView';
import {OfflineModeButton} from './OfflineModeButton';

const Stack = createStackNavigator();

const headerRight = () => {
  return <OfflineModeButton />;
};

const headerLeft = () => {
  return <LogoutButton />;
};

export const App = () => {
  return (
    <>
      <SafeAreaProvider>
        <NavigationContainer>
          <Stack.Navigator>
            <Stack.Screen
              name="List"
              component={ItemListView}
              options={{
                headerTitleAlign: 'center',
                headerLeft,
                headerRight,
              }}
            />
          </Stack.Navigator>
        </NavigationContainer>
    </>
  );
};

AppWrapper:

//AppWrapper.tsx
import React from 'react';
import {StyleSheet, View, ActivityIndicator} from 'react-native';
import {AppProvider, UserProvider, RealmProvider} from '@realm/react';
import {appId, baseUrl} from '../atlasConfig.json';

import {App} from './App';
import {WelcomeView} from './WelcomeView';

import {Item} from './ItemSchema';
import {Animal} from './AnimalSchema';

const LoadingIndicator = () => {
  return (
    <View>
      <ActivityIndicator size="large" />
    </View>
  );
};

export const AppWrapper = () => {
  return (
    <AppProvider id={appId} baseUrl={baseUrl}>
      <UserProvider fallback={WelcomeView}>
        <RealmProvider
          schema={[Item, Animal]}
          sync={{
            flexible: true,
            onError: (_session, error) => {
              console.error(error);
            },
          }}
          fallback={LoadingIndicator}>
          <App />
        </RealmProvider>
      </UserProvider>
    </AppProvider>
  );
};

ItemListView:

//ItemListView.tsx
import React, {useCallback, useState, useEffect} from 'react';
import {BSON} from 'realm';
import {useUser, useRealm, useQuery} from '@realm/react';
import {SafeAreaProvider} from 'react-native-safe-area-context';
import {FlatList, Text, View} from 'react-native';
import {ListItem} from '@rneui/base';

import {Item} from './ItemSchema';
import {Animal} from './AnimalSchema';

export function ItemListView() {
  const realm = useRealm();
  const items = useQuery(Item)
  const animals = useQuery(Animal)
  const user = useUser();

  useEffect(() => {
    console.log('Products:', items);
    console.log('Animals:', animals);
  }, [items, animals]);

  return (
    <SafeAreaProvider>
      <View>
        <FlatList
          keyExtractor={item => item._id.toString()}
          data={items}
          renderItem={({item}) => (
            <ListItem
                key={`${item._id}`}
                bottomDivider
                topDivider
                hasTVPreferredFocus={undefined}
                tvParallaxProperties={undefined}>
             <Text>{item.priority}</Text>
              <ListItem.Title>
                {item.name}
              </ListItem.Title>
            </ListItem>
          )}
        />
      </View>
    </SafeAreaProvider>
  );
};

Additionally:

  • I changed my appId in atlasConfig.json in order to point at myApp in mongodbAtlas/AppServices.
  • Shemas were creating from client in AppServices/myApp/Schemas → by turn ON-OFF In mongodbAtlas/myApp/AppServices/DeviceSync (‘my_database’ was selected as database).
  • Rules in AppServices/myApp/Rules were changed to allow read and write in collection ‘Animal’ on database ‘my_database’ for all users.
  • Documents were inserted in collection ‘Animal’ on database ‘my_database’.
  • I tried reinstall App.
  • I tried change attributte schemaVersion in RealmProvider tag.

Question:
¿WHY console.log in ItemListView.tsx doesn’t show in log any data for ‘animals’ (‘animals’ get an empty array)? On the other hand, console.log show items and items is a not empty array with all documents of collection ‘Item’ on database ‘my_database’

¿Any missing configuration or missing file or missing code?

Thanks in advance

Based on what you’ve shared, you’re missing the subscription part of Device Sync. In the original template app’s ItemListView.tsx, check out lines 36-56.

Your implementation doesn’t need to be this complicated, but you do need to set up a subscription. This is how the backend and client establish what data to share. Because you don’t have a subscription, updates in your backend Animal collection are not synced to the client, because the client doesn’t know that the collection exists or that you want to sync it.

For more details about sync subscriptions, check out the docs: https://www.mongodb.com/docs/realm/sdk/react-native/sync-data/flexible-sync/#subscribe-to-a-query

We could probably do a better job explaining the subscriptions for the template app.

Oh, thanks a lot.
Your answer is the solution.
I added the next lines below the lines that you mean:

useEffect(() => {
    realm.subscriptions.update(mutableSubs => {
      mutableSubs.add(
        realm.objects(Animal)
      );
    });
  }, [realm, user]);

console shows Animal collection documents.
I’ll read more about subscriptions.

1 Like

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.