Curso de React Native

React Native nos permite crear aplicaciones reales nativas para iOS y Android basado en React JS. Utilizando ReactJS, en lugar de obtener una aplicación web híbrida, obtenemos una aplicación real nativa.
Una aplicación híbrida es aquella que ejecuta código HTML, CSS y Javascript dentro de un componente de la aplicación móvil destinado a cargar páginas web (una especie de iframe). Una aplicación nativa es la que está programada utilizando el lenguaje nativo de la plataforma.

El código que programemos usando React Native será traducido al lenguaje nativo de la plataforma, mientras que cuando desarrollamos una aplicación híbrida, ejecutamos código HTML, CSS y JavaScript dentro de esta especie de iframe.

Para programar una aplicación nativa para Android, necesitaríamos conocer el lenguaje Kotlin, mientras que si la aplicación es para IOS, necesitaríamos saber Swift. Sin embargo, con React Native, podremos realizar una aplicación nativa para ambas plataformas conociendo una sola tecnología.

Las aplicaciones nativas, respecto de las aplicaciones híbridas, tienen:

  • Mejor rendimiento
  • Menor consumo de memoria.
  • Mayor velocidad.

Crear una aplicación en React Native con Expo

El siguiente comando creará una aplicación que utilizará la navegación expo router.

npx create-expo-app .

Si quisieramos utilizar la navegación de React Navigation, ejecutaríamos el siguiente comando.

npx create-expo-stack --react-navigation .

Si quisieramos escoger el tipo de plantilla a partir de la cual crearemos nuestra aplicación, ejecutaremos el siguiente comando:

npx create-expo-app . --template

Ejecutar nuestra aplicación de Expo

1. Ejecutamos el proyecto que hemos creado

npm start

2. Instalamos la aplicación Expo en el teléfono móvil: Expo

5. Para desplegar escanearemos el código qr generado. Para evitar problemas…

  • En el teléfono móvil Android, iremos a ajustes → Aplicaciones → Expo → Mostrar sobre otras apps.
  • Es probable que tengas actualizar el método start del package.json para añadir la opción de tunnel:
"scripts": {
    "start": "expo start --tunnel",
    ...
},

Solución de errores al ejecutar

  • CommandError: ngrok tunnel took too long to connect

Menú de inicio de windows → Windows Security → Virus & threat protection → Virus & threat protection settings → Manage settings → Real-time protection → Off

Actualizar Expo

Algunos problemas utilizando expo pueden solucionarse simplemente actualizándolo:

expo upgrade

Instalación de módulos en un proyecto de Expo

No debemos instalar los módulos utilizando npm, ya que este gestor de dependencias, por defecto, instala siempre la última versión del módulo y puede ocurrir que esta no sea compatible con la versión de Expo que estamos usando. En lugar del comando npm, utilizaremos el comando expo.

npx expo install nombre-modulo

Ejecutando la aplicación en el emulador

1. Debemos tener instalado Android Studio.

2. Si estamos usando windows, tendremos que añadir las siguientes variables de entorno a nivel de sistema.

ANDROID_HOME → C:\Users(name)\AppData\Local\Android\Sdk
Añadir al Path → C:\Users(name)\AppData\Local\Android\Sdk\platform-tools

Esto evitarárá el típico error:

ADB no se reconoce como un comando interno o externo.

2. Creamos y arrancamos un nuevo Device Manager:

Curso de React Native 1

Componentes básicos de React Native

View

Equivalente a los div de HTML. Sirve para agrupar componentes.

import { View } from 'react-native';
<View><View>

Text

import { Text } from 'react-native';
<Text>El texto<Text>

TextInput

<TextInput onChangeText={text => setStateValue(text)}/>

Image

import { Image } from 'react-native';
import image from 'ruta-imagen/image.png';

<Image source={image} />

Scroll

El componente SafeAreaView evita que el contenido se meta por debajo de la status bar.

while(premium == false) verCodigo = false;

Para poder ver el código fuente, accede o suscríbete.

Suscríbete

Pressable

while(premium == false) verCodigo = false;

Para poder ver el código fuente, accede o suscríbete.

Suscríbete

Listado de elementos:

Este componente permite renderizar sólo los elementos de la lista que se están viendo en pantalla, siendo más óptimas que usar combinaciones de etiquetas <View> y <Text> dentro de un map cuando tengamos un listado de muchos elementos.

El atributo keyExtractor es utilizado para identificar de manera inequivoca a cada registro, igual que hacíamos con el atributo key cuando usábamos un map en ReactJS.

El atributo numRows no actualiza los cambios on The Fly o en caliente, lo cual significa que tendrás que volver a ejecutar la aplicación para que el cambio surta efecto.

while(premium == false) verCodigo = false;

Para poder ver el código fuente, accede o suscríbete.

Suscríbete

Configuración de firebase en expo

En este enlace tienes una configuración adicional que debes codificar en el firebase.js para mantener los datos del usuario logueado cuando utilizas firebase con expo:

https://github.com/expo/fyi/blob/main/firebase-js-auth-setup.md

Debemos instalar el siguiente módulo:

npx expo install @react-native-async-storage/async-storage

Nuestra configuración quedaría así:

while(premium == false) verCodigo = false;

Para poder ver el código fuente, accede o suscríbete.

Suscríbete

styled-components en react-native

Es posible utilizar Styled Components en React native sin ningún tipo de limitación. Sin embargo, para maquetar los componentes en React Native, hemos de tener en cuenta lo siguiente:

  • El valor por defecto el estilo display es flex. Los posibles valores de este estilo son: flex y none.
  • El valor por defecto del estilo flex-direction es column, al contrario de lo que ocurre en una aplicación web, es es row.
  • La unidad de medida que usaremos será px. Ni %, ni em, ni rem.
while(premium == false) verCodigo = false;

Para poder ver el código fuente, accede o suscríbete.

Suscríbete

Al usar styled-components en React native no puedes mezclarlos con estilos nativos en línea. El siguiente ejemplo sería incorrecto:

<MyStyledComponent style={{marginTop:'6px'}} />

Media queries

while(premium == false) verCodigo = false;

Para poder ver el código fuente, accede o suscríbete.

Suscríbete

Cargar tipografías

while(premium == false) verCodigo = false;

Para poder ver el código fuente, accede o suscríbete.

Suscríbete

Módulos útiles

React native vector icons

npx expo install react-native-vector-icons

Permite incrustar iconos en nuestra aplicación pertenecientes a múltiples colecciones de iconos.

import Icon from 'react-native-vector-icons/Ionicons';
...
<Icon name="rocket" size={30} color="#900" />

Esta es la lista de iconos disponibles con su correspondiente codigo que lo carga:

https://oblador.github.io/react-native-vector-icons/

https://www.npmjs.com/package/react-native-vector-icons

expo-av

Permite cargar un video en el background.

npx expo install expo-av

https://docs.expo.dev/versions/latest/sdk/av/

React native svg

npx expo install react-native-svg

Documentación.

Expo Image Picker

npx expo install expo-image-picker

Permite seleccionar imágenes de la galería de fotos.

https://docs.expo.dev/versions/latest/sdk/imagepicker/

React native modal

npx expo install react-native-modal

Cargaremos una librería externa para hacerlo.

React native maps

npx expo install react-native-maps

Integra un mapa de google maps en nuestra aplicación.

https://docs.expo.dev/versions/latest/sdk/map-view/

Date Time Picker

npx expo install @react-native-community/datetimepicker

Permite seleccionar fechas.

https://www.npmjs.com/package/@react-native-community/datetimepicker

React Native Sign In

Este módulo no funciona con Expo GO. Tendremos que usarlo utilizando una Development Build

https://www.npmjs.com/package/@react-native-google-signin/google-signin

Paquetes de elementos de la user Interface

Expo camera

npx expo install expo-camera

Habrá que establecer una configuración en el fichero app.json para poder hacer las fotos.

/app.json

while(premium == false) verCodigo = false;

Para poder ver el código fuente, accede o suscríbete.

Suscríbete

/src/components/CameraComponent.js

while(premium == false) verCodigo = false;

Para poder ver el código fuente, accede o suscríbete.

Suscríbete

/src/screens/Home.js

while(premium == false) verCodigo = false;

Para poder ver el código fuente, accede o suscríbete.

Suscríbete

https://www.npmjs.com/package/expo-camera

<BottomTab.Screen name="Nombre Screen 1" component={StackNav}    

Ejercicio React Native

Listado

Hacer una aplicación que cargue un array de de elementos en un FlatList y tenga un cuadro de texto que le permita al usuario podrá añadir nuevos elementos.

Tener en cuenta que para detectar cuando un texto cambia dentro de un input usaremos onChangeText en lugar de onChange.

<TextInput onChangeText={text => setTxt(text)} />
Curso de React Native 2

Cuando el usuario pulse sobre un elemento de la lista se le preguntará al usuario si desea borrar el elemento.

Curso de React Native 3

Expo router

Este sistema de navegación utiliza React Navigation internamente (documentado más abajo). Es mucho más sencilla de usar y es mi opción recomendada.

Para poder usarlo, debemos instalarlo:

npx expo install expo-router

Cuando usamos expo-router debemos cambiar el punto de entrada a la aplicación. Para ello, remplazaremos la propiedad main del package.json de nuestra plantilla blank por la siguiente propiedad main. Después de esto, podremos borrar el fichero App.js.

/package.json

{
  "name": "react native app",
  "version": "1.0.0",
  "main": "expo-router/entry",
  ...

Con Stack Navigation

Estableceremos la configuración de la navegación principal en este fichero:

/app/_layout.jsx

while(premium == false) verCodigo = false;

Para poder ver el código fuente, accede o suscríbete.

Suscríbete

/app/(stack)/_layout.jsx

import { Stack } from "expo-router";

const _layout = () => {
  return (
    <Stack>
      <Stack.Screen name="Page1" />
      <Stack.Screen name="Page2" />
    </Stack>
  );
};

export default _layout;

Las screens por las que navegaremos estarán dentro de la carpeta app. La screen donde se inicia la navegación debe llamarse index.js. Sólo debe haber una página de inicio (index.jsx), que estará en (stack), (drawer) o (bottom) según nos convenga.

Independientemente de cual sea el primer Stack del layout, index.js será el punto de inicio de la aplicación.

/app/(stack)/index.js

while(premium == false) verCodigo = false;

Para poder ver el código fuente, accede o suscríbete.

Suscríbete

/app/(stack)/Home2.js

while(premium == false) verCodigo = false;

Para poder ver el código fuente, accede o suscríbete.

Suscríbete

Paso de parámetros en Stack Navitagion

while(premium == false) verCodigo = false;

Para poder ver el código fuente, accede o suscríbete.

Suscríbete

while(premium == false) verCodigo = false;

Para poder ver el código fuente, accede o suscríbete.

Suscríbete

Con Drawer Navigation

Debemos instalar las siguientes dependecias:

while(premium == false) verCodigo = false;

Para poder ver el código fuente, accede o suscríbete.

Suscríbete

Y utilizar el siguiente código:

/src/app/(drawer)/_layout.jsx

while(premium == false) verCodigo = false;

Para poder ver el código fuente, accede o suscríbete.

Suscríbete

Con Bottom Navigation

/app/index.js

El fichero de la configuración de las tabs debe estar en una carpeta llamada (tabs).

Expo irá a buscar la navegación por tabs sólo si no existe un fichero index.js en la raíz de la carpeta app.

/app/(tabs)/_layout.jsx

while(premium == false) verCodigo = false;

Para poder ver el código fuente, accede o suscríbete.

Suscríbete

El fichero index.jsx será el que se cargue por defecto en una navegación con tabs. Es un fichero necesario.

/app/(tabs)/index.jsx

while(premium == false) verCodigo = false;

Para poder ver el código fuente, accede o suscríbete.

Suscríbete

/app/(tabs)/Page2.jsx

while(premium == false) verCodigo = false;

Para poder ver el código fuente, accede o suscríbete.

Suscríbete

React Navigation

Ten en cuenta que es probable que esta navegación de problemas cuando la ejecutemos en en el navegador web.

Instalación de las dependencias del core de react navigator:

while(premium == false) verCodigo = false;

Para poder ver el código fuente, accede o suscríbete.

Suscríbete

Stack Navigation

La stack navigation es similar a la que realizamos en nuestro navegador web mediante los botones de avanzar y retroceder página.

Imagina que tu aplicación móvil tiene tres páginas: A, B y C. Empiezas tu navegación en la página A. Pulsas un botón que te lleva a la página B. El stack queda así: B, A y C. Además, aparece el botón en pantalla de ir a la página anterior, en este caso, la página A. Si lo pulso, el stack quedaría así: A, B y C. Si pulso en ir a la página C, el stack quedaría así: C, A, B. Nuevamente, si pulso en ir a la página anterior, iríamos a la página A y la página C quedaría en la última posición. El stack quedaría así: A, B y C.

Si una navegación esta vinculada a una pantalla (como la stack navitation que estamos creando en este paso), la carpeta de navegación estará dentro de la carpeta de la pantalla. Si una navegación es global (como la bottom navigation que crearemos más adelante), estará en la carpeta navigation.

Instalación de las dependecias expecíficas de stack navigation:

npx expo install @react-navigation/stack

/App.js

while(premium == false) verCodigo = false;

Para poder ver el código fuente, accede o suscríbete.

Suscríbete

/src/navigation/index.js

while(premium == false) verCodigo = false;

Para poder ver el código fuente, accede o suscríbete.

Suscríbete

/src/screens/Page1.jsx

while(premium == false) verCodigo = false;

Para poder ver el código fuente, accede o suscríbete.

Suscríbete

Paso de parámetros

Envío:

while(premium == false) verCodigo = false;

Para poder ver el código fuente, accede o suscríbete.

Suscríbete

Recogida:

while(premium == false) verCodigo = false;

Para poder ver el código fuente, accede o suscríbete.

Suscríbete

Bottom Navigation

Vamos a interar la Bottom Navigation dentro del StackNavigation principal.

while(premium == false) verCodigo = false;

Para poder ver el código fuente, accede o suscríbete.

Suscríbete

/src/navigation/index.js

while(premium == false) verCodigo = false;

Para poder ver el código fuente, accede o suscríbete.

Suscríbete

/src/navigation/bottom/index.jsx

while(premium == false) verCodigo = false;

Para poder ver el código fuente, accede o suscríbete.

Suscríbete

Integrando una Stack Navigation en la Bottom Navigation que está dentro de la Stack Navigation principal

Añadiremos una StackNavigation a la BottomNavigation:

import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import BottomScreen1 from '../../screens/BottomScreen1';
import AnotherNavigationfrom 'navigation/stack/AnotherNavigation';

const BottomTab = createBottomTabNavigator();

const BottomNav = () => (
  <BottomTab.Navigator>
    <BottomTab.Screen name="Nombre Screen 1" component={BottomScreen1} />
    <BottomTab.Screen name="Nombre Screen 2" component={AnotherNavigation} options={{ headerShown: false }} />

  </BottomTab.Navigator>
);

export default BottomNav;

La nueva StackNavigation que hemos importado en la BottomNavigation, podría tener este código:

import { createStackNavigator } from '@react-navigation/stack';
import Page2 from '../../screens/Page2';
import BottomScreen2 from '../../screens/BottomScreen2';

const Stack = createStackNavigator();

const AnotherNavigation = () => {
  return (
    <Stack.Navigator>
      <Stack.Screen
        name="BottomScreen2"
        component={BottomScreen2}

      />
      <Stack.Screen
        name="Page2"
        component={Page2}
        options={{ headerShown: false }}
      />
    </Stack.Navigator>
  );
}

export default AnotherNavigation;

Tenemos dos opciones:

  • Modificar el componente BottomTabs para obtener un comportamiento global de todas las screens.
  • Modificar el Tab.Screen que nos interese en cada caso.
while(premium == false) verCodigo = false;

Para poder ver el código fuente, accede o suscríbete.

Suscríbete

/src/navigation/bottom/bottom-config.js

while(premium == false) verCodigo = false;

Para poder ver el código fuente, accede o suscríbete.

Suscríbete

En las pantallas individuales, para establecer la configuración, utilizaremos options en lugar de screenoptions.

/src/screen/Page2/screen-config.js

while(premium == false) verCodigo = false;

Para poder ver el código fuente, accede o suscríbete.

Suscríbete

Cómo utilizar variables de entorno en una aplicación creada con Expo

Utilizaremos la siguiente sintaxis para acceder a una variable de entorno definida en el fichero .env:

process.env.EXPO_PUBLIC_API_KEY // No te olvides del prefijo EXPO_PUBLIC_

Subida de imágenes a Firebase

Utilizaremos el expo-image-picker:

while(premium == false) verCodigo = false;

Para poder ver el código fuente, accede o suscríbete.

Suscríbete

Geolocalización

while(premium == false) verCodigo = false;

Para poder ver el código fuente, accede o suscríbete.

Suscríbete

Persistiendo la información

npx expo install @react-native-async-storage/async-storage

https://react-native-async-storage.github.io/async-storage/docs/install/

Podemos usar el siguiente componente para gestionar el valor. Tener en cuenta que debemos almacenar texto (podemos convertir un objeto en texto con JSON.stringify) y que la clave con la que guardamos el valor también debe ser texto.

while(premium == false) verCodigo = false;

Para poder ver el código fuente, accede o suscríbete.

Suscríbete

Trabajo con mapas: calcular distancias, ver si un punto cae dentro de cierto radio…

https://www.npmjs.com/package/geolib

Compilar / Build

Para Android:

Debemos instalar el siguiente módulo en el sistema operativo:

npm install -g eas-cli

También actualizaremos el fichero package.json con los siguientes scripts:

while(premium == false) verCodigo = false;

Para poder ver el código fuente, accede o suscríbete.

Suscríbete

Debemos tener el siguiente fichero en la raíz del proyecto:

eas.json
while(premium == false) verCodigo = false;

Para poder ver el código fuente, accede o suscríbete.

Suscríbete

Ejecutamos en la terminal el comando:

eas login

Panadería

1. Hacer una screen Home que lea el siguiente fichero de datos y pinte una rejilla utilizando el componente FLatList con cada uno de los elementos.

Curso de React Native 4

./data/categories.js

export const CATEGORIES = [
    {
        id: 1,
        name: 'Categoría 1',
        color: '#896978'
    },
    {
        id: 2,
        name: 'Categoría 2',
        color: '#839791'
    },
    {
        id: 3,
        name: 'Categoría 3',
        color: '#aac0af'
    },
    {
        id: 4,
        name: 'Categoría 4',
        color: '#896978'
    },
]

2. Utilizando Stack Navigation, al pulsar en uno de los elementos de Home, debemos navegar al Screen Productos de la categoría en la que haremos una consulta a Firebase para recuperar los productos correspondientes a la categoría seleccionada.

Puedes alimentar tu aplicación con productos consultando la api de mercadolibre y haciendo una insercción de productos en Firebase a partir de los datos recuperados.

Para pasar parámetros de una pantalla a otra, puedes consultar la documentación que vimos anteriormente.

Curso de React Native 5

3. Al pulsar sobre un producto iremos a una tercera screen en la que recuperaremos los datos del mismo.

Curso de React Native 6

4. También tendremos la opción de añadir el producto a un carrito. Gestionaremos este carrito utilizando Context API para almacenar los datos.

Para navegar al carrito utilizaremos Bottom Tab Navigator.

El bottom tab navigator tendrá dos menús. Uno enlzará al stack navigator que acabamos de hacer y otro al screen Cart.

5. Debemos tener un stack con dos screens: login y registro. Si el usuario no esta logueado, cargaremos el creen de login, y si no el stack de navegación que ya teníamos:

src/navigation/index.js
import React, { useEffect, useState } from 'react';
import { NavigationContainer } from '@react-navigation/native';
import TabsNavigator from './bottomtabs/TabsNavigator';
import { onAuthStateChanged } from 'firebase/auth';
import { auth } from '../app/firebase';
import AuthScreen from '../screens/AuthScreen';

const MainNavigator = () => {
    const [isLogged, setIsLogged] = useState(false);

    useEffect(() => {
        onAuthStateChanged(auth, user => {
            if (user) {
                console.log('user', user);
                const uid = user.uid;
                setIsLogged(true);
            } else {
                console.log("No user logged");
                setIsLogged(false);
            }
        });
    }, []);

    return (<NavigationContainer>
        {isLogged ?
            <TabsNavigator /> :
            <AuthScreen />
        }
    </NavigationContainer>)

}

export default MainNavigator;

Ejecutar sin Expo GO

Creamos el fichero eas.json:

{
  "build": {
    "development": {
      "developmentClient": true,
      "distribution": "internal"
    },
    "preview": {
      "distribution": "internal"
    },
    "production": {}
  }
}

package.json:

{

  "scripts": {
    ...
    "build-dev": "eas build --platform android --profile development",
  },

Cuando ejectutamos esto…

1. Aparecerá un QR en la terminal, que al ser escaneada nos permitirá descargar una aplicación en modo desarrollo.

2. Ejecutamos el comando habitual npm start . Aparecerá un nuevo QR que debemos escanear y seleccionar la opción development build. A partir de aquí, la aplicación se actualizará según hagamos cambios en el código fuente.