Foto del autor Osledy Bazo

Primeros pasos con React Native

Se acabaron los días de sentarse en el ordenador. En pleno 2017 la interacción y consumo de contenido se hace comúnmente a través de dispositivos móviles. React Native usa reactjs, un framework de javascript orientado a componentes. Su manejo de estados nos da una excelente plataforma, lo más moderno en tecnologías web para el desarrollo de apps. Con React Native no crearás una "aplicación HTML5" ni una "aplicación híbrida" debido a que usa componentes nativos de Android y iOS.

¡Empecemos!

Te enseñaré una app sencilla, para este ejemplo usaré linux y la compilaré para android. Primero debes instalar nodejs para ejecutar la cli de react native, descarga node en su página oficial https://nodejs.org/es/

Puedes verificar que está instalado tecleando en consola

                node -v

Debería aparecer algo como 'v7.6.0'

Luego de instalar node debes instalar el cli de react a través de npm

                npm install -g react-native-cli

Ahora vamos con el proyecto.

                react-native init MiNuevoProyecto

Esto creará un directorio llamado MiNuevoProyecto e instalará algunas dependencias. Entra a el directorio

                cd MiNuevoProyecto/

Por otro lado necesitarás Java SE Development Kit(JDK), descárgalo en el siguiente link http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html, así mismo sigue los siguientes pasos que son esenciales para desarrollar un entorno para Android

1. Android Studio.


Descarga aquí https://developer.android.com/studio/index.html A la hora de instalar escoge "Custom" y checkea las siguientes opciones:

  • Android SDK
  • Android SDK Platform
  • Android Virtual Device



2. SDK

Por defecto se instalará el SDK más actual, pero necesitarás el SDK Android 6.0 (Marshmallow) para trabajar con react native. El mismo lo puedes instalar desde Android studio. En la Pantalla de bienvenida


selecciona "Configurar" > "SDK Manager".


En la pestaña platforms checkea la casilla "Android 6.0 (Marshmallow)" y luego la casilla inferior izquierda "Show Package Details" y asegúrate que esté checkeado lo siguiente:

  • Google APIs
  • Android SDK Platform 23
  • Google APIs Intel x86 Atom_64 System Image


En la pestaña "SDK Tools" checkea la casilla "Show Package Details".
Expande "Android SDK Build-Tools" y selecciona "23.0.1"
Ahora haz click en "Apply" para empezar la descarga


3. Variables de Entorno (ANDROID_HOME):

En linux busca el archivo de configuración de bash “$HOME/.bash_profile” o “$HOME/.bashrc” y agrega las siguientes líneas:

                export ANDROID_HOME=$HOME/Android/Sdk
                export PATH=$PATH:$ANDROID_HOME/tools
                export PATH=$PATH:$ANDROID_HOME/platform-tools

Tipea el siguiente comando para recargar los cambios:

                source $HOME/.bash_profile

Bien, asegúrate de tener los drivers de tu teléfono instalados y activa la opción "Depuración USB", esto permitirá a Android Debug Bridge (ADB) comunicarse con tu dispositivo y hacer las instalaciones correctas al momento de desarrollar. Puedes leer mas sobre AD aquí https://developer.android.com/studio/command-line/adb.html

Para verificar que tu dispositivo está conectado puedes escribir este comando

Nota: tu version de android debe ser mayor o igual a android 4.1

                $ adb devices
                List of devices attached
                * daemon not running. starting it now at tcp:5037 *
                * daemon started successfully *
                479008af21f7905c        device

En este ejemplo el dispositivo “479008af21f7905c” está listo para usarse

Si todo está en orden ejecuta este comando para iniciar nuestra app:

                react-native run-android

Ahora deberías ver el template por defecto que viene en “index.android.js” Este es el código por defecto

                jsx
                /**
                 * Sample React Native App
                 * https://github.com/facebook/react-native
                 * @flow
                 */
                
                import React, { Component } from 'react';
                import {
                  AppRegistry,
                  StyleSheet,
                  Text,
                  View
                } from 'react-native';
                
                export default class MiNuevoProyecto extends Component {
                  render() {
                    return (
                      <View style={styles.container}>
                        <Text style={styles.welcome}>
                          Welcome to React Native!
                        </Text>
                      </View>
                    );
                  }
                }
                const styles = StyleSheet.create({
                  container: {
                    flex: 1,
                    justifyContent: 'center',
                    alignItems: 'center',
                    backgroundColor: '#F5FCFF',
                  },
                  welcome: {
                    fontSize: 20,
                    textAlign: 'center',
                    margin: 10,
                  },
                  instructions: {
                    textAlign: 'center',
                    color: '#333333',
                    marginBottom: 5,
                  },
                });
                
                AppRegistry.registerComponent('MiNuevoProyecto', () => MiNuevoProyecto);


Juega un poco con el código!

Hay varias cosas que debes tener en cuenta, como que ReactJs usa jsx para la interfaz gráfica y para los estilos se usan inline styles con “StyleSheet” del paquete react native.

Edita la clase “MiNuevoProjecto”.

                jsx
                export default class MiNuevoProyecto extends Component {
                  constructor() {
                    // Estado por defecto
                    this.state = {
                      name: 'Coders Venezuela!'
                      texto: ''
                    }
                    this.syncText = this.syncText.bind(this);
                  }
                  syncText() {
                    this.setState({
                      name: this.state.texto
                    });
                  }
                  render() {
                    return (
                      <View style={styles.container}>
                        <Text style={styles.welcome}>
                          Hola {this.state.name}
                        </Text>
                        <TextInput
                          style={styles.input}
                          onSelectionChange={this.syncText}
                          onChangeText={t => this.setState({texto: t})}
                          value={this.state.texto}
                        />
                      </View>
                    );
                  }
                }

Lo que acabas de hacer es agregar un estado por defecto a nuestra app. También se añadió un método que va a sincronizar el nuevo input que agregaste con lo que muestra la etiqueta Text que está arriba.

Algunos estilos

                 jsx
                const styles = StyleSheet.create({
                  container: {
                    flex: 1,
                    justifyContent: 'center',
                    alignItems: 'center',
                    backgroundColor: '#FFF8DF',
                  },
                  text: {
                    color: '#d45500',
                    fontSize: 20,
                    textAlign: 'center',
                    margin: 10,
                  },
                  input: {
                    color: '#d45500',
                    fontSize: 20,
                    height: 50,
                    width: 200,
                    borderColor: 'yellow',
                    borderWidth: 1
                  }
                });




¡Con esto tendrás lista la app!Si deseas seguir investigando acerca de react native puedes hacerlo en la página oficial https://facebook.github.io/react-native/

Aquí tienes la documentación guía y tutorial https://facebook.github.io/react-native/docs/tutorial.html

Foto del autor Osledy Bazo

React Native y AirBnB Google Maps

En este post explicare como integrar Google Maps a tus aplicaciones React Native, ya que me he encontrado que la instalación por defecto genera muchos errores y react-native no termina de reconocer la librería de Google Maps.

Después de estar aproximadamente 1 semana intentando integrar la librería de AirBnB de Google Maps a una aplicación he llegado a una serie de pasos fáciles de seguir.

Creación del proyecto React Native e instalación de librería AirBnB Google Maps

Primero creamos nuestra app en React Native, nuestra app se llamará myMapApp

                    > react-native init myMapApp
                    > cd myMapApp

Ahora instalamos la librería para Google Maps de AirBnB

                    > npm install --save react-native-maps

Enlazamos la librería con React Native

                    > npm install
                    > react-native link react-native-maps

En teoría ya nuestra app debería funcionar con los mapas por defecto de cada plataforma Maps en iOS y Maps en Android. Pero si queremos usar Google Maps en ambas plataformas tendremos que hacer algunos pasos adicionales:

Antes de comenzar a trabajar en la app vamos a generar la clave de Api (Api Key) de Google Maps para que usemos en nuestro proyecto

Crear la clave API de Google Maps

Iremos a la consola de Google para desarrolladores

Crearemos un nuevo proyecto

Y agregaremos una api en nuestro caso Google Maps SDK for iOS y Google Maps SDK for Android

Ahora nos iremos al menú de la izquierda en Credenciales. Y crearemos nuestra API Key, la guardaremos para mas adelante

Enlace de AirBnB Google Maps para iOS

Instalar Cocoapods (si lo tenemos podemos saltar este paso)

                      sudo gem install cocoapods

Configurar el proyecto para iOS

                      cd ios
                      pod init

Esto genera un archivo Podfile en nuestra, lo abriremos y editaremos su contenido

                      # Uncomment the next line to define a global platform for your project
                      platform :ios, '9.0'
                
                      target 'myMapApp' do
                        # Uncomment the next line if you're using Swift or would like to use dynamic frameworks
                        # use_frameworks!
                
                        # Pods for myMapApp
                
                        target 'myMapApp-tvOSTests' do
                          inherit! :search_paths
                          # Pods for testing
                        end
                
                        target 'myMapAppTests' do
                          inherit! :search_paths
                          # Pods for testing
                        end
                
                        react_native_path = "../node_modules/react-native"
                        pod "yoga", :path => "#{react_native_path}/ReactCommon/yoga"
                        pod "React", :path => react_native_path
                
                        pod 'GoogleMaps'
                
                      end

Recuerda reemplazar el nombre de tu aplicación donde dice target

Y no te olvides de especificar la plataforma de iOS que utilizaras

Si recibes este error:

                      [!] The name of the given podspec `yoga` doesn't match the expected one `Yoga`

Cambia la linea de este modo (yoga en minúscula):

                      pod "yoga", :path => "#{react_native_path}/ReactCommon/yoga"

Ahora en la terminal

                      pod install

Al hacer esto se generara un nuevo proyecto en nuestra carpeta de iOS, lo abriremos con XCode

                      open myMapApp.xcworkspace

Y copiamos la carpeta AirGoogleMaps que se encuentra dentro de /node_modules/react-native-maps/lib/ios al proyecto xcworkspace que tenemos abierto en el Xcode.

Quedando de esta forma

Para usar las credenciales API abrimos el archivo AppDelegate.m en Xcode

                    #import "AppDelegate.h"
                
                    #import <React/RCTBundleURLProvider.h>
                    #import <React/RCTRootView.h>
                    @import GoogleMaps;
                    @implementation AppDelegate
                
                    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
                    {
                      NSURL *jsCodeLocation;
                      [GMSServices provideAPIKey:@"YOUR_GOOGLE_API_KEY"];
                      jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
                
                      RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
                                                                          moduleName:@"myMapApp"
                                                                  initialProperties:nil
                                                                      launchOptions:launchOptions];
                      rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];
                
                      self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
                      UIViewController *rootViewController = [UIViewController new];
                      rootViewController.view = rootView;
                      self.window.rootViewController = rootViewController;
                      [self.window makeKeyAndVisible];
                      return YES;
                    }
                
                    @end

Ahora iremos a Product -> Clean y luego Product -> Build para ejecutar nuestra aplicación.

Enlace de AirBnB Google Maps para Android

En nuestro proyecto debemos editar el archivo android/app/build.gradle

                    dependencies {
                      ...
                      // Paste these line
                      compile(project(':react-native-maps')){
                          exclude group: 'com.google.android.gms', module: 'play-services-base'
                          exclude group: 'com.google.android.gms', module: 'play-services-maps'
                      }
                      compile 'com.google.android.gms:play-services-base:10.0.1'
                      compile 'com.google.android.gms:play-services-maps:10.0.1'
                    }

Y también debemos agregar nuestra Api Key en Android/app/src/AndroidManifest.xml

                    <application>
                        <!-- You will only need to add this meta-data tag, but make sure it's a child of application -->
                        <meta-data
                          android:name="com.google.android.geo.API_KEY"
                          android:value="YOUR GOOGLE MAPS API KEY HERE"/>
                    </application>

Con esto ya tenemos nuestro proyecto React Native configurado en iOS y Android con Google Maps, ahora actualizamos el archivo App.js en nuestro proyecto React Native para incluir el Mapa

                  import React, { Component } from 'react';
                  import {
                    StyleSheet,
                    Text,
                    View
                  } from 'react-native';
                  import MapView, {PROVIDER_GOOGLE} from 'react-native-maps';
                
                  const styles = StyleSheet.create({
                    container: {
                      ...StyleSheet.absoluteFillObject,
                      height: 400,
                      width: 400,
                      justifyContent: 'flex-end',
                      alignItems: 'center',
                    },
                    map: {
                      ...StyleSheet.absoluteFillObject,
                    },
                  });
                
                  export default class App extends Component {
                    render() {
                      const { region } = this.props;
                      console.log(region);
                
                      return (
                        <View style ={styles.container}>
                          <MapView
                            provider={PROVIDER_GOOGLE}
                            style={styles.map}
                            region={{
                              latitude: 37.78825,
                              longitude: -122.4324,
                              latitudeDelta: 0.015,
                              longitudeDelta: 0.0121,
                            }}
                          >
                          </MapView>
                        </View>
                      );
                    }
                  }
Foto del autor Osledy Bazo

Ejemplos del uso del teclado en React-Native para iPhone y Android

Según la documentación de Facebook para el componente de Teclado tenemos disponibles varios eventos para interactuar con el teclado de nuestra aplicación. https://facebook.github.io/react-native/docs/keyboard.html

Comencemos con un ejemplo de app básica donde sólo mostraremos una caja de texto para ingresar texto y un párrafo para indicar el estado del teclado, si está activo o no.

Si te has dado cuenta, al tocar el input puedes escribir cualquier texto, pero luego al tocar la pantalla fuera de la caja de texto, el teclado no se esconde.

Para solucionar esto debemos usar otro componente llamado 'TouchableWithoutFeedback'

https://facebook.github.io/react-native/docs/touchablewithoutfeedback.html

Te recomiendo leas la documentación sobre este componente ya que debe usarse con cuidado.

Modificaremos nuestro código para incluir el modulo del teclado 'Keyboard' y de 'TouchableWithoutFeedback'. También agregaremos este nuevo componente alrededor de nuestro View principal y usaremos 'onPress={Keyboard.dismiss}' para esconder el teclado una vez tocado la pantalla fuera de la caja de texto.

Para acceder a los estados del teclado tenemos que usarlo en combinacion con un Event Listener que conectará con un evento nativo, puede ser identificado con alguno de estos strings:

  • keyboardWillShow (IOS)
  • keyboardWillHide (IOS)
  • keyboardDidShow (Android)
  • keyboardDidHide (Android)
  • keyboardWillChangeFrame
  • keyboardDidChangeFrame

Modificaremos nuestra app y agregaremos métodos para estar atentos al cambio del teclado.

Usare los strings 'keyboardDidShow' y 'keyboardDidHide' ya que en funcionan tanto en Android como en IOS. ('keyboardWillShow' y 'keyboardWillHide' no tienen representación nativa en Android).

Ademas de agregar los EventListener tenemos que recordar que hay que removerlos, esto para prevenir memory leaks y problemas de rendimiento en nuestra aplicación.

Ahora cambiaremos el estado de nuestro status a un string que indica si el teclado esta activo o inactivo.

En los eventos del keyboard podemos acceder a algunas de sus propiedades como son:

                { 
                  endCoordinates: { 
                  screenY: 442, 
                  screenX: 0, 
                  width: 375, 
                  height: 225 
                },
                  startCoordinates: { 
                  screenY: 451, 
                  screenX: 0, 
                  width: 375, 
                  height: 216 
                },
                  duration: 250 
                }
                

Hay un ultimo problema que es muy común a la hora de trabajar con el teclado en una aplicación y es que a veces el teclado puede tapar parte del contenido de nuestra app:

Para solucionarlo debemos usar el componente 'KeyboardAvoidingView', este componente esta diseñado para ajustar o mover lo que se ve en la pantalla automaticamente para que el teclado no estorbe.

https://facebook.github.io/react-native/docs/keyboardavoidingview.html

Hay tres formas para hacer esto automaticamente y la que uses dependerá de los resultados que quieras mostrar. Presta atención a la propiedad 'keyboardVerticalOffset' que sirve para guardar una distancia entre la vista y el teclado. Para esto tendremos que modificar un poco nuestro código así: