1.- Introducción
Ya creamos un api rest para registrar un usuario, iniciar sesión para obtener un jsonwebtoken y actualizar el perfil de usuario. Ahora vamos a crear una aplicación en react native con redux y react-navigation para hacer uso de esta api rest.
2.- Instalación
Necesitamos instalar el generador de react native que puedes revisar la documentación en el siguiente enlace y para crear nuestra app usamos el siguiente comando:
create-react-native-app herelodin.com
Ahora vamos a la carpeta que acaba de generar react native con el comando
cd herelodin.com
debemos inizializar nuestra aplicación utilizamos el comando
react-native eject
que se encargara que crear la carpeta ios y android para cada plataforma por el momento vamos a utilizar redux para almacenar toda la información en la aplicación y react-navigation para transiciones utilizamos el siguiente comando para instalar las dependencias.
yarn add react-redux redux redux-logger redux-persist redux-thunk react-navigation axios --save
3.- Estructura
Por experiencia debemos tener estructurados correctamente nuestra aplicacion, definir componentes, screens, reducers y actions, despues de algunos años y de trabajo en equipo llegamos a la siguiente estructura como óptima.
- src carpeta que contiene toda la estructura de nuestra app
- components aqui agregamos todos los componentes de nuestra app como botones, inputs, iconos etc…
- config en esta carpeta podemos agregar todas las rutas para conectarnos a nuestra api y los stylos de nuestros components
- i18n si la app tuviera mas de 1 idioma aqui agregamos los archivos json para los idiomas correspondientes
- redux
- actions aqui colocamos todas nuestras acciones por ejemplo hacer una peticion para registrar un usuario
- reducers en esta carpeta creamos la estructura de nuestros datos.
- screens agregamos todas las pantalls de nuestra app por ejemplo la pantalla register que manda a llamar a los componentes para registrar un usuario
- utils en esta carpeta creamos funciones que podemos utilizar en nuestro proyecto como por ejemplo validar un email y no tener que crear la funcion en cada lugar que se requiera.
4.- Comó configurar reducers
Vamos a crear nuestro primer reducers donde vamos almacenar los datos de usuario y el token de la sesión.
Para esto vamos a la carpeta redux/reducers y creamos el archivo session.js
import { SET_SESSION, CLEAR_SESION, SET_USER } from '../ActionTypes.js' const session = (state = { }, action) => { switch (action.type) { case SET_USER : { const { user } = action return { ...state, user } } case CLEAR_SESION: { return { }; } case SET_SESSION : { const { token, user } = action return { token, user } } default: { return state } } } export default session;
Donde vamos a importar de nuestro archivo ActionTypes.js las variables SET_SESSION, CLEAR_SESSION Y SET_USER que se encargaran de definir cada acción, ahora vamos a crear en la misma carpeta el archivo index que se encarga de combinar todos los reducers aunque en este caso solo tenemos uno https://github.com/herel/react-native-redux-registro-de-usuarios/blob/master/src/redux/reducers/index.js
import { combineReducers } from 'redux'; import session from './session'; const reducers = combineReducers({ session }); export default reducers;
Listo ya tenemos nuestro primer reducers, se que esto es algo complicado de entender pero si sigues estos pasos te bajas el repo y con algo de practica podras dominar redux.
5.- Comó configurar redux, persistStore, store y PersistGate.
Ahora cada vez que inicie nuestra aplicación en react debemos cargar los datos que en ella se encuentran por ejemplo los datos de usuario y la sesión, si es la primera vez que se abre la app debemos cargar los valores por default para esto debemos ir a nuestro archivo principal index.js y utilizar el siguiente codigo:
import React, { Component } from 'react' import { AppRegistry } from 'react-native'; /*redux configuration*/ import { applyMiddleware, compose, createStore } from 'redux' import { persistStore, persistReducer } from 'redux-persist' import storage from 'redux-persist/lib/storage' import { PersistGate } from 'redux-persist/integration/react' import { Provider } from 'react-redux' import { createLogger } from 'redux-logger' import reducers from './src/redux/reducers' import thunk from 'redux-thunk'; //app views and components import App from './src'; const loggerMiddleware = createLogger({ predicate: () => false }) const persistedReducer = persistReducer({ key: 'root', storage, blacklist: ['filter', 'modals'] }, reducers) function configureStore (initialState) { const enhancer = compose( applyMiddleware(thunk, loggerMiddleware) ) return createStore(persistedReducer, initialState, enhancer) } const initialState = {} export const store = configureStore(initialState) export const persistor = persistStore(store) export default class Herelodin extends Component { render () { return ( <Provider store={store}> <PersistGate loading={null} persistor={persistor}> <App /> </PersistGate> </Provider> ) } } AppRegistry.registerComponent('herelodin', () => Herelodin);
Ya implementamos redux en nuestra aplicación mientras la app carga los datos podemos mostrar algun splash en este caso deje el valor en null y una vez que redux carga los datos se inicializa nuestra app.
6.- Comó configurar StackNavigator
Ya tenemos configurado redux, con nuestro primer reduxcers y nuestro provider que se encargar de inyectar la data a nuestra app, ahora debemos definir las pantallas (screens) que vamos a utlizar por el momento solo vamos a mostrar el formulario de registro de usuarios para esto vamos al archivo src/index.js
import React, { Component } from 'react'; import { StackNavigator } from 'react-navigation'; import Form from './screens/Form.js'; const Navigation = StackNavigator({ home : { screen : Form } },{ headerMode: 'none' }); export default Navigation;
¡Genial! ya creamos el primer screen de nuestra App llamada home donde manda a llamar al componente Form que se encuentra dentro de la carpeta screens en este archivo vamos a importar el component Input que se encargara de mostrar los 4 inputs para nombre, apellidos, email y contraseña.
7. Como crear componentes en react native
Como comente en el punto anterior necesitamos crear la mayor parte de componentes para reutlizar en toda nuestra app y no tener que repetir el codigo para esto vamos a crear el component input en la siguiente ruta src/components/Input.js
import React, { Component } from 'react'; import { View, TextInput } from 'react-native'; import { InputContainer, InputStyle } from '../config/styles'; class Input extends Component{ render(){ return ( <View style={InputContainer}> <TextInput placeholder={this.props.placeholder} placeholderTextColor="rgba(255,255,255,0.3)" style={InputStyle} value={this.props.value} keyboardType={this.props.keyboardType} autoCapitalize='none' underlineColorAndroid='transparent' secureTextEntry={this.props.secureTextEntry} onChangeText={this.props.onChangeText} autoCorrect={false} /> </View> ) } } export default Input;
Como notaron en este componente importamos estilos por default que podemos reutilizar en otro componente el value del input viene de los props de igual forma si el valor del input cambiar se ejecuta la funcion onChague que tambien viene de los props como vemos no guardamos nigun dato en este componente ya que la idea es reutilizarlo en toda la app.
8.- Reutilizar componentes
Es muy importante reutilizar componentes para que nuestra app sea lo más óptima posible en este ejemplo tenemos 4 inputs pero no creamos 4 veces el mismo codigo, lo que hicimos fue crear un componente llamado input y asi solo llamarlo en nuestro screen y pasarle los atributos para que se adapte para un campo de email, contraseña ó solo texto.
En nuestro archivo src/screens/form.js reutilizamos el componente así:
import React, { Component } from 'react'; import { View } from 'react-native'; import Input from '../components/Input'; import LinearGradient from 'react-native-linear-gradient'; import { container } from '../config/styles'; class Form extends Component{ constructor(props){ super(props); this.state = { firstName : '', lastName : '', email : '', password : '' } } render(){ return ( <LinearGradient colors={['#441E35','#320622']} style={container}> <Input placeholder="Nombre(s)" onChangeText={(firstName) => this.setState({firstName})} value={this.state.firstName} /> <Input placeholder="Apellido(s)" onChangeText={(lastName) => this.setState({lastName})} value={this.state.lastName} /> <Input placeholder="Apellido(s)" onChangeText={(email) => this.setState({email})} value={this.state.email} /> <Input secureTextEntry={true} placeholder="Contraseña" onChangeText={(password) => this.setState({password})} value={this.state.password} /> </LinearGradient> ); } } export default Form;
Cada vez que el usuario ingrese su nombre, emai y contraseña se ejecuta la funcion onChangeText y asignamos el valor a nuestro state asi reutilizamos de forma correcta el componente.
8.1- Como validar campos en react native
Ahora debemos agregar un botón con el texto “Registrar” pero si el usuario no ha ingresado ningun dato este botón debe estar deshabilidado (disabled) para esto creamos un componente llamado Button.js
import React, { Component } from 'react'; import { View, TouchableHighlight , Text } from 'react-native'; import { button, button_text } from '../config/styles'; import { REDCOLOR } from '../config/const'; class Button extends Component{ onPress(){ if(this.props.onPress) this.props.onPress(); } _getBackground(){ if(this.props.disabled) return { backgroundColor : 'rgba(255,255,255,0.5)' } return { backgroundColor : REDCOLOR }; } render(){ return ( <TouchableHighlight activeOpacity={1} underlayColor="rgba(255,255,255,.6)" onPress={this.onPress.bind(this)} style={[button,this._getBackground()]}> <Text style={button_text}>{this.props.text}</Text> </TouchableHighlight> ); } } export default Button;
Ahora importamos el boton en nuestro formulario y agregamos la funcion getDisabled que validara si los campos de nombre, email y contraseña son correctos.
import React, { Component } from 'react'; import { View } from 'react-native'; import Input from '../components/Input'; import Button from '../components/Button'; import LinearGradient from 'react-native-linear-gradient'; import { container } from '../config/styles'; class Form extends Component{ constructor(props){ super(props); this.state = { firstName : '', lastName : '', email : '', password : '' } } _getDisabled(){ let disabled = false; if(!this.state.firstName || this.state.firstName.length <=4) disabled = true; if(!this.state.lastName || this.state.lastName.length <=4) disabled = true; if(!this.state.email) disabled = true; if(!this.state.password || this.state.password.length <=5) disabled = true; return disabled; } render(){ return ( <LinearGradient colors={['#441E35','#320622']} style={container}> <Input placeholder="Nombre(s)" onChangeText={(firstName) => this.setState({firstName})} value={this.state.firstName} /> <Input placeholder="Apellido(s)" onChangeText={(lastName) => this.setState({lastName})} value={this.state.lastName} /> <Input placeholder="Correo electrónico" onChangeText={(email) => this.setState({email})} value={this.state.email} /> <Input secureTextEntry={true} placeholder="Contraseña" onChangeText={(password) => this.setState({password})} value={this.state.password} /> <Button disabled={this._getDisabled()} text="Registrar" /> </LinearGradient> ); } } export default Form;
si ejecutamos nuestra app con el comando react-native run-ios obtenemos el siguiente resultado
Gracias por leer y comentar en el siguiente post vamos a implementar actions para enviar la información de la app a nuestra api, te dejo algunos lirbos que me ayudaron mucho para mejorar las buenas practicas a la hora de programar.