Join us at MongoDB.local London on 7 May to unlock new possibilities for your data. Use WEB50 to save 50%.
Register now >
Docs Menu
Docs Home
/ /
Atlas App Services

Tutorial: Atlas Device Sync para React Native

Estimated time to complete: 30 minutes, depending on your experience with React Native

Puede utilizar el SDK de Realm React Native y @realm/reaccionar Para crear una aplicación móvil con React Native. Este tutorial te muestra cómo crear tu propia aplicación con Flexible Sync.

Para este tutorial, iniciaremos con una aplicación de plantilla de TypeScript previamente creada para ver cómo todo encaja.

La aplicación es una plantilla prediseñada que incluye una aplicación React Native funcional (frontend) y sus archivos de configuración de aplicación de App Services correspondientes (backend).

La aplicación de plantilla es una aplicación básica de lista de tareas que permite a los usuarios realizar diversas acciones para gestionar sus tareas:

  • Cree cuentas de correo electrónico/contraseña e inicie y cierre sesión en la aplicación.

  • Crear, leer, actualizar y eliminar sus propias tareas.

  • Ver todas las tareas, incluso si el usuario no es el propietario.

Una vez que la aplicación de plantilla esté en funcionamiento, agregará una nueva priority campo al modelo Item existente y actualice la suscripción de Sincronización Flexible para que solo muestre elementos dentro de un rango de prioridades. Este ejemplo ilustra cómo adaptar la aplicación de plantilla a sus necesidades. Dada la estructura actual de la aplicación de plantilla, no es necesario realizar este cambio.

La aplicación de plantilla proporciona un interruptor que simula el dispositivo sin conexión. Este interruptor permite probar rápidamente la sincronización del dispositivo, simulando que el usuario no tiene conexión a internet. Sin embargo, es probable que este interruptor se elimine en una aplicación de producción.

Nota

Consulte el inicio rápido

Si prefieres explorar por tu cuenta en lugar de seguir un tutorial guiado, consulta la Guía de inicio rápido de React Native. Incluye ejemplos de código copiables y la información esencial necesaria para configurar una aplicación React Native con Atlas Device Sync.

  • Debes configurar tu entorno local para el desarrollo con React Native antes de comenzar este tutorial. Para obtener instrucciones detalladas, consulta "Configuración del entorno de desarrollo" en la documentación de React Native.

  • Este tutorial comienza con una aplicación de Plantilla. Necesitas una Cuenta de Atlas, una clave API y App Services CLI para crear una aplicación de plantilla.

    • Para obtener más información sobre cómo crear una cuenta de Atlas, consulte la sección Primeros pasos con Atlas. Para este tutorial, necesita una cuenta de Atlas con un clúster de nivel gratuito.

    • También necesita una clave API de Atlas para la cuenta de MongoDB Cloud con la que desea iniciar sesión. Debe ser propietario del proyecto para crear una aplicación de plantilla mediante la CLI de App Services.

    • Para aprender más sobre cómo instalar App Services CLI, consulta Instalar App Services CLI. Después de instalar, ejecuta el comando login utilizando la clave API de tu proyecto Atlas.

Este tutorial se basa en la aplicación de plantilla de sincronización flexible del SDK de React Native, denominada react-native.todo.flex. Comenzamos con la aplicación predeterminada y creamos nuevas funciones a partir de ella.

Para obtener más información sobre las aplicaciones de plantilla, consulte Aplicaciones de plantilla.

Si aún no tiene una cuenta Atlas, regístrese para implementar una aplicación de plantilla.

Siga el procedimiento descrito en la guía Crear una aplicación de servicios de aplicaciones y seleccione Create App from TemplateSeleccione la plantilla Real-time Sync. Esto crea una aplicación de Servicios de Aplicaciones preconfigurada para usarla con uno de los clientes de la plantilla de Sincronización de Dispositivos.

Después de crear una aplicación plantilla, la Interfaz de Usuario muestra un modal etiquetado como Get the Front-end Code for your Template. Este modal proporciona instrucciones para descargar el código cliente de la aplicación plantilla como un archivo .zip o para usar App Services CLI y obtener el cliente.

Después de seleccionar el método .zip o la CLI de App Services, siga las instrucciones en pantalla para obtener el código de cliente. Para este tutorial, seleccione el código de cliente JavaScript (React Native).

Nota

La utilidad ZIP predeterminada de Windows podría mostrar el archivo .zip vacío. Si esto ocurre, use un programa de compresión de terceros disponible.

El comando de creación de aplicaciones appservices configura el backend y crea una aplicación de plantilla React Native para que la uses como base para este tutorial.

Ejecute el siguiente comando en una ventana de terminal para crear una aplicación llamada "MyTutorialApp" que se implementa en la región US-VA con su entorno configurado en "desarrollo" (en lugar de producción o control de calidad).

appservices app create \
--name MyTutorialApp \
--template react-native.todo.flex \
--deployment-model global \
--environment development

El comando crea un nuevo directorio en su ruta actual con el mismo nombre que el valor del indicador --name.

Puedes bifurcar y clonar un repositorio de GitHub que contenga el código del cliente de Device Sync. El código del cliente de React Native está disponible en https://github.com/mongodb/template-app-react-native-todo.

Si usas este proceso para obtener el código del cliente, debes crear una aplicación de plantilla para usar con el cliente. Sigue las instrucciones en Crear una aplicación de plantilla para usar la Interfaz de Usuario de Atlas App Services, los App Services CLI o la API de Administración para crear una aplicación de plantilla Device Sync.

Utilice los siguientes pasos para poner en funcionamiento la aplicación de plantilla en su computadora:

1

En tu terminal, ve al directorio que contiene el código del cliente. Si creaste la aplicación con la CLI de App Services, ve a MyTutorialApp/react-native.todo.flex. De lo contrario, ve a la raíz del proyecto descargado o clonado. Luego, ejecuta los siguientes comandos para instalar las dependencias de la aplicación:

npm install

Para compilar y ejecutar la aplicación en un dispositivo o simulador iOS, instale las dependencias de iOS adicionales con CocoaPods.

cd ios
npx pod-install
2

En este punto, deberías tener una aplicación React Native completamente funcional que pueda ejecutarse en iOS, Android o ambos.

Si encuentras un error u otro problema, asegúrate de que tu entorno React Native esté configurado correctamente. Consulta la guía oficial de React Native sobre configuración del entorno de desarrollo. Sigue todos los pasos para tu SO de desarrollo y tu SO objetivo.

Para asegurarse de que todo funcione en iOS, cree la aplicación y ejecútela en un simulador de iOS:

npm run ios

Para asegurarse de que todo funciona en Android:

  1. Inicia un emulador de Android. Consulta "Ejecutar aplicaciones en el emulador de Android" para obtener más información.

  2. Construye la aplicación en el emulador:

    npm run android

    Un error común es Error: spawn ./gradlew EACCES. Esto significa que los permisos del archivo del proyecto no son los adecuados. En macOS, puedes solucionarlo introduciendo chmod 755 android/gradlew en tu terminal.

3

When the build completes, you should have a functional app running on your simulator. In the app, register a new account and test the features:

  • Añade algunos elementos por hacer a la lista.

  • Presione la casilla de verificación en uno o dos elementos para marcarlos como completados.

  • Press the X on an item to delete it from the list.

  • Toggle internet connectivity in the app to simulate offline mode.

Si te conectas a tu clúster Atlas y consultas la colección todo.Item, podrás ver los datos de tu aplicación. Mientras la aplicación React Native no esté en modo sin conexión, los nuevos datos y cambios se sincronizan automáticamente con la colección todo.Item.

Tip

Para saber cómo conectarse a su clúster Atlas, consulte Conectarse a un clúster Atlas.

De igual forma, cualquier cambio en la colección se sincroniza automáticamente con la app React Native. Intenta cambiar el estado de finalización de un elemento en tu clúster: la app React Native se actualizará automáticamente con el nuevo valor siempre que haya una conexión de red disponible.

Tip

To learn more about updating data in your cluster, see Update Documents.

Now that you have the template app running let's dive into the code to see what we're working with.

La aplicación de plantilla incluye una aplicación de Servicios de Aplicaciones completamente configurada en el directorio backend. Tiene un valor appId único en atlasConfig.json que las aplicaciones cliente usan para conectarse.

También incluye las siguientes configuraciones predefinidas:

  • Una fuente de datos vinculada a su clúster Atlas.

  • Un modelo de datos para la colección todo.Item que coincide con la clase Item en la aplicación React Native.

  • Un proveedor de autenticación que permite a los usuarios registrarse e iniciar sesión en tu aplicación con un correo electrónico y contraseña.

  • Una configuración de sincronización flexible con un solo rol de sesión que permite a los usuarios leer y escribir sus propios elementos y ver los elementos de otros usuarios.

La aplicación React Native es un cliente móvil completamente configurado que puede ejecutarse en dispositivos iOS y Android.

La aplicación utiliza la biblioteca @realm/react. Esta biblioteca incluye ganchos y componentes de React que optimizan el trabajo con el backend de Atlas y la base de datos de Realm.

La aplicación contiene algunos archivos de configuración y directorios, pero puedes ignorarlos a menos que quieras personalizarla. Para este tutorial, debes estar familiarizado con los componentes de React en el directorio source/:

File Name
Descripción

ItemSchema.tsx

La clase Item, incluyendo su modelo de datos de objetos. Importamos esta clase en AppWrapper.tsx para incluirla en el esquema general de Realm de la aplicación.

AppWrapper.tsx

This is the root component for the app. It functions as a wrapper component and contains all of the @realm/react providers. This is where you configure your realm and your connection to your Atlas backend.

App.tsx

La mayor parte de la funcionalidad de la aplicación se encuentra en este componente y sus componentes secundarios. Dado que los proveedores @realm/react están integrados en este componente, puede acceder a una instancia de su backend Atlas, a objetos de usuario e interactuar con la base de datos de Realm.

WelcomeView.tsx

El formulario de registro e inicio de sesión que los usuarios ven al abrir la aplicación por primera vez.

ItemListView.tsx

The main to-do list app that users interact with after they log in. It queries for Item Realm objects and displays them in a list. It also includes the code to create new Item objects and store them in Realm.

CreateToDoPrompt.tsx

A UI form that lets us enter data for new Item objects. The code that actually creates new objects is in ItemListView.tsx.

LogoutButton.tsx

A reusable button that logs out an authenticated user.

OfflineModeButton.tsx

Un botón reutilizable que simula un modo fuera de línea al pausar y reanudar el Realm syncSession actual.

Ahora que está más familiarizado con lo que ya se proporciona en la aplicación de plantilla, escribamos algo de código para implementar una nueva función.

Para este tutorial, añadirás una nueva propiedad priority a los objetos Item. Esto nos permitirá organizar las tareas según su importancia y centrarnos únicamente en las más relevantes.

1

Queremos permitir un pequeño número de niveles de prioridad nominales, y queremos poder ordenarlos fácilmente. Para ello, utilizaremos una función de ayuda para definir un objeto enum que mapee un conjunto de nombres de niveles ordenados hacia y desde un entero que represente su prioridad.

Agregue el siguiente código directamente debajo de las declaraciones de importación en source/ItemSchema.tsx:

function createEnum(arr) {
arr.forEach((p, i) => arr[p] = i);
return arr;
}
// Priority.High === 1
// Priority[Priority.High] === "High"
export const Priority = createEnum([
"Severe",
"High",
"Medium",
"Low",
])

Los niveles de prioridad en enum se ordenan de mayor a menor importancia. El valor del índice correspondiente a cada nivel aumenta del más importante, Priority[0], al menos importante, Priority[3]. Esto significa que un nivel de prioridad más alto (es decir, más importante) tiene un valor de índice más bajo.

2

Ahora tenemos un enum que define los posibles valores del campo priority. Sin embargo, aún debemos definir el campo priority en la clase Item.

Add the following lines to your code in source/ItemSchema.tsx to add priority to the Item data model:

source/ItemSchema.tsx
export class Item extends Realm.Object<Item> {
_id!: BSON.ObjectId;
isComplete!: boolean;
summary!: string;
owner_id!: string;
priority!: string;
static schema: Realm.ObjectSchema = {
name: 'Item',
primaryKey: '_id',
properties: {
// This allows us to automatically generate a unique _id for each Item
_id: {type: 'objectId', default: () => new BSON.ObjectId()},
// All todo items will default to incomplete
isComplete: {type: 'bool', default: false},
summary: 'string',
owner_id: 'string',
priority: {
// Store the index value of the Priority enum rather than the name
type: 'int',
default: Priority.High
},
},
};
}

Nota

¿Por qué no se rompió la sincronización?

En este punto, tu modelo Item de React Native y su esquema correspondiente en tu aplicación de App Services ya no coinciden. ¡No te preocupes!

Adding a property to a Realm object is not a breaking change and therefore does not require a client reset. The template app has Development Mode enabled, so changes to the client Realm object are reflected in the server-side schema. For more information, see Development Mode and Update Your Data Model.

3

El modelo de datos de tu aplicación ahora incluye un priority por cada objeto Item. Actualicemos la interfaz de usuario de la aplicación para que puedas elegir un valor de prioridad al añadir una nueva tarea a la lista.

Primero, instalaremos una librería externa para implementar el componente selector de prioridad. Ejecute lo siguiente en su terminal dentro de la carpeta raíz de su proyecto:

npm install @react-native-picker/picker

Si está desarrollando para iOS, asegúrese de vincular los Cocoapods asociados después de instalar el paquete:

npx pod-install

Tip

Es posible que tengas que reconstruir tu aplicación después de instalarla. Para ello, detén el empaquetador de tu proyecto y ejecuta el comando de compilación:

npm run ios
npm run android

Ahora que el paquete está completamente instalado, actualicemos el nuevo componente de solicitud de creación de tareas pendientes para usar el selector.

Add the following imports to the top of source/CreateToDoPrompt.tsx:

import {Picker} from '@react-native-picker/picker';
import {Priority} from './ItemSchema';

Luego, modifique el componente CreateToDoPrompt:

  • Agregar priority a la definición de propiedades onSubmit()

  • Realizar un seguimiento de priority en un gancho de estado

  • Connect the state to the Picker component that you imported

  • Pasa priority al controlador onSubmit()

source/CreateToDoPrompt.tsx
type Props = {
onSubmit(args: {summary: string; priority: string;}): void;
};
export function CreateToDoPrompt(props: Props): React.ReactElement<Props> {
const {onSubmit} = props;
const [summary, setSummary] = useState('');
const [priority, setPriority] = useState(Priority.High);
return (
<View style={styles.modalWrapper}>
<Text h4 style={styles.addItemTitle}>
Add To-Do Item
</Text>
<Input
placeholder="What do you want to do?"
onChangeText={(text: string) => setSummary(text)}
autoCompleteType={undefined}
/>
<Picker
style={{width: '80%'}}
selectedValue={priority}
onValueChange={value => setPriority(value)}>
{Priority.map(priority => (
<Picker.Item
key={priority}
label={priority}
value={Priority[priority]}
/>
))}
</Picker>
<Button
title="Save"
buttonStyle={styles.saveButton}
onPress={() => onSubmit({summary, priority})}
/>
</View>
);
}

En source/ItemListView.tsx, modifica la función createItem() para aceptar y usar priority:

source/ItemListView.tsx
const createItem = useCallback(
({summary, priority}: {summary: string, priority: string}) => {
realm.write(() => {
return new Item(realm, {
summary,
owner_id: user?.id,
priority
});
});
},
[realm, user],
);

Luego, modifique el controlador de envío de creación de tareas para aceptar el nivel priority y pasarlo a createItem():

source/ItemListView.tsx
<CreateToDoPrompt
onSubmit={({summary, priority}) => {
setShowNewItemOverlay(false);
createItem({summary, priority});
}}
/>

Por último, modifica la plantilla del elemento de la lista para renderizar el priority de la tarea pendiente antes del summary:

source/ItemListView.tsx
<ListItem
key={`${item._id}`}
bottomDivider
topDivider
hasTVPreferredFocus={undefined}
tvParallaxProperties={undefined}>
<Text>{item.priority}</Text>
<ListItem.Title style={styles.itemTitle}>
{item.summary}
</ListItem.Title>
<ListItem.Subtitle style={styles.itemSubtitle}>
{item.owner_id === user?.id ? '(mine)' : ''}
</ListItem.Subtitle>
<ListItem.CheckBox
checked={item.isComplete}
checkedColor={COLORS.primary}
iconType="material"
checkedIcon="check-box"
uncheckedIcon="check-box-outline-blank"
onPress={() => toggleItemIsComplete(item._id)}
/>
<Button
type="clear"
onPress={() => deleteItem(item._id)}
icon={
<Icon
type="material"
name="clear"
size={12}
color="#979797"
tvParallaxProperties={undefined}
/>
}
/>
</ListItem>
4

Your app should now allow users to set a priority level for new to-do items.

Rebuild the app and open it. Add some new to-do items to confirm that you can choose a priority level and that the list displays each to-do's priority.

El protocolo Device Sync utiliza un modelo flexible donde cada cliente de sincronización utiliza una consulta RQL estándar para seleccionar un subconjunto de datos de la aplicación y luego se suscribe a él. Esto extrae automáticamente la última versión de todos los datos del subconjunto al dispositivo y sincroniza los cambios entre dispositivos.

Por ejemplo, la aplicación de plantilla que estás usando tiene la siguiente suscripción incorporada a los artículos que posee el usuario actual:

source/ItemListView.tsx
realm.subscriptions.update(mutableSubs => {
mutableSubs.removeByName(itemSubscriptionName);
mutableSubs.add(
realm.objects(Item).filtered(`owner_id == "${user?.id}"`),
{name: ownItemsSubscriptionName},
);
});

Puedes personalizar la suscripción durante la ejecución para sincronizar solo los datos que tu aplicación necesita. Añadamos una función para demostrar cómo.

For this tutorial, we'll add a button that lets us toggle between two modes: one where the app syncs all to-do items and another where it only syncs important ones with a priority of High or Severe.

1

First, add a useState() hook to the ItemListView component to keep track of the current mode:

ItemListView.tsx
const [showImportantOnly, setShowImportantOnly] = useState(false);

A continuación, agregue un nuevo botón que conmute la moda en la parte inferior de la lista de quehaceres, después de <ListItem>:

source/ItemListView.tsx
<Button
title={showImportantOnly ? 'Show All' : 'Show Important Only'}
buttonStyle={{
...styles.addToDoButton,
backgroundColor: showImportantOnly ? '#00A35C' : '#FFC010',
}}
onPress={() => setShowImportantOnly(showImportantOnly => !showImportantOnly)}
/>
2

En este punto, la aplicación puede cambiar de modo en la interfaz de usuario, pero no hemos hecho nada más, por lo que los modos son funcionalmente idénticos. Actualicemos la suscripción de sincronización para que solo sincronice los datos relevantes para el modo actual.

In the first useEffect of the ItemListView component, add code that checks the current mode and appends an additional priority filter to the query if the showImportantOnly mode is active:

source/ItemListView.tsx
useEffect(() => {
if (showAllItems) {
realm.subscriptions.update(mutableSubs => {
mutableSubs.removeByName(ownItemsSubscriptionName);
mutableSubs.add(realm.objects(Item), {name: itemSubscriptionName});
});
} else if (showImportantOnly) {
realm.subscriptions.update(mutableSubs => {
mutableSubs.removeByName(itemSubscriptionName);
mutableSubs.add(
realm.objects(Item).filtered(`owner_id == "${user?.id}" && priority <= 1`),
{name: ownItemsSubscriptionName},
);
});
} else {
realm.subscriptions.update(mutableSubs => {
mutableSubs.removeByName(itemSubscriptionName);
mutableSubs.add(
realm.objects(Item).filtered(`owner_id == "${user?.id}"`),
{name: ownItemsSubscriptionName},
);
});
}
}, [realm, user, showAllItems, showImportantOnly]);

Importante

No olvide agregar showImportantOnly a la lista de dependencias en el segundo argumento de useEffect.

3

Tu aplicación ya está configurada para modificar su suscripción de sincronización según el modo actual.

Rebuild and run the app to make sure everything works. You should be able to create, complete, and delete to-do items as well as toggle between viewing all items and only important items.

Tip

Cambiar suscripciones con el modo de desarrollador habilitado

In this tutorial, when you change the subscription and query on the priority field for the first time, the field is automatically added to the Device Sync Collection Queryable Fields. This occurs because the template app has Development Mode enabled by default. If Development Mode was not enabled, you would have to manually add the field as a queryable field to use it in a client-side Sync query.

Para obtener más información, consulte Campos consultables.

Nota

Share Feedback

¿Cómo te fue? Usa el Rate this page widget en la parte inferior derecha de la página para evaluar su efectividad. O reporta un problema en el repositorio de GitHub si tuviste algún problema.

Next

¿Qué son los servicios de aplicación Atlas?