Creación de aplicaciones móviles con React Native y WordPress
Publicado: 2022-03-10Como desarrolladores web, es posible que haya pensado que el desarrollo de aplicaciones móviles requiere una nueva curva de aprendizaje con otro lenguaje de programación. Quizás deba agregar Java y Swift a su conjunto de habilidades para comenzar a trabajar con iOS y Android, y eso podría atascarlo.
¡Pero este artículo te tiene en una sorpresa! Analizaremos la creación de una aplicación de comercio electrónico para iOS y Android utilizando la plataforma WooCommerce como nuestro backend. Este sería un punto de partida ideal para cualquier persona que desee iniciarse en el desarrollo multiplataforma nativo.
Una breve historia del desarrollo multiplataforma
Es 2011 y vemos el comienzo del desarrollo de aplicaciones móviles híbridas. Frameworks como Apache Cordova, PhoneGap e Ionic Framework emergen lentamente. Todo se ve bien y los desarrolladores web están codificando ansiosamente las aplicaciones móviles con su conocimiento existente.
Sin embargo, las aplicaciones móviles todavía se parecían a las versiones móviles de los sitios web. No hay diseños nativos como el diseño de materiales de Android o el aspecto plano de iOS. La navegación funcionó de manera similar a la web y las transiciones no fueron suaves como la mantequilla. Los usuarios no estaban satisfechos con las aplicaciones creadas con el enfoque híbrido y soñaban con la experiencia nativa.
Un avance rápido hasta marzo de 2015, y React Native aparece en escena. Los desarrolladores pueden crear aplicaciones multiplataforma verdaderamente nativas utilizando React, una biblioteca de JavaScript favorita para muchos desarrolladores. Ahora pueden aprender fácilmente una pequeña biblioteca además de lo que saben con JavaScript. Con este conocimiento, los desarrolladores ahora apuntan a la web, iOS y Android.
Además, los cambios realizados en el código durante el desarrollo se cargan en los dispositivos de prueba casi al instante. Esto solía tomar varios minutos cuando teníamos desarrollo nativo a través de otros enfoques. Los desarrolladores pueden disfrutar de los comentarios instantáneos que solían amar con el desarrollo web.
Los desarrolladores de React están más que felices de poder usar los patrones existentes que han seguido en una plataforma completamente nueva. De hecho, apuntan a dos plataformas más con lo que ya conocen muy bien.
Todo esto es bueno para el desarrollo front-end. Pero , ¿qué opciones tenemos para la tecnología de back-end? ¿Todavía tenemos que aprender un nuevo lenguaje o marco?
La API REST de WordPress
A fines de 2016, WordPress lanzó la tan esperada API REST en su núcleo y abrió las puertas a soluciones con backends desacoplados.
Entonces, si ya tiene un sitio web de WordPress y WooCommerce y desea conservar exactamente las mismas ofertas y perfiles de usuario en su sitio web y aplicación nativa, ¡este artículo es para usted!
Suposiciones hechas en este artículo
Lo guiaré a través del uso de su habilidad de WordPress para crear una aplicación móvil con una tienda WooCommerce usando React Native. El artículo asume:
- Está familiarizado con las diferentes API de WordPress, al menos en un nivel de principiante.
- Estás familiarizado con los conceptos básicos de React.
- Tienes un servidor de desarrollo de WordPress listo. Yo uso Ubuntu con Apache.
- Tiene un dispositivo Android o iOS para probar con Expo.
Lo que construiremos en este tutorial
El proyecto que vamos a construir a través de este artículo es una aplicación de tienda de moda. La aplicación contará con las siguientes funcionalidades:
- Página de la tienda que enumera todos los productos,
- Página de un solo producto con detalles del artículo seleccionado,
- Función 'Agregar al carrito',
- Función 'Mostrar artículos en el carrito',
- Función 'Eliminar artículo del carrito'.
Este artículo tiene como objetivo inspirarlo a usar este proyecto como punto de partida para crear aplicaciones móviles complejas utilizando React Native.
Nota : para la aplicación completa, puede visitar mi proyecto en Github y clonarlo .
Comenzando con nuestro proyecto
Comenzaremos a construir la aplicación según la documentación oficial de React Native. Después de instalar Node en su entorno de desarrollo, abra el símbolo del sistema y escriba el siguiente comando para instalar la aplicación Create React Native globalmente.
npm install -g create-react-native-app
A continuación, podemos crear nuestro proyecto.
create-react-native-app react-native-woocommerce-store
Esto creará un nuevo proyecto React Native que podemos probar con Expo.
A continuación, necesitaremos instalar la aplicación Expo en nuestro dispositivo móvil que queremos probar. Está disponible tanto para iOS como para Android.
Al instalar la aplicación Expo, podemos ejecutar npm start en nuestra máquina de desarrollo.
cd react-native-woocommerce-store npm start
Después de eso, puede escanear el código QR a través de la aplicación Expo o ingresar la URL dada en la barra de búsqueda de la aplicación. Esto ejecutará la aplicación básica 'Hello World' en el móvil. Ahora podemos editar App.js para realizar cambios instantáneos en la aplicación que se ejecuta en el teléfono.
Alternativamente, puede ejecutar la aplicación en un emulador. Pero por brevedad y precisión, cubriremos su ejecución en un dispositivo real.
A continuación, instalemos todos los paquetes necesarios para la aplicación con este comando:
npm install -s axios react-native-htmlview react-navigation react-redux redux redux-thunk
Configuración de un sitio de WordPress
Dado que este artículo trata sobre la creación de una aplicación React Native, no entraremos en detalles sobre la creación de un sitio de WordPress. Consulte este artículo sobre cómo instalar WordPress en Ubuntu. Dado que la API REST de WooCommerce requiere HTTPS, asegúrese de configurarla con Let's Encrypt. Consulte este artículo para obtener una guía práctica.
No estamos creando una instalación de WordPress en localhost ya que ejecutaremos la aplicación en un dispositivo móvil y también porque se necesita HTTPS.
Una vez que WordPress y HTTPS se hayan configurado correctamente, podemos instalar el complemento WooCommerce en el sitio.
Después de instalar y activar el complemento, continúe con la configuración de la tienda WooCommerce siguiendo el asistente. Una vez que se complete el asistente, haga clic en 'Volver al panel'.
Será recibido por otro aviso.
Haga clic en 'Vamos' para 'Agregar productos de ejemplo'. Esto nos ahorrará el tiempo de crear nuestros propios productos para mostrarlos en la aplicación.
Archivo de constantes
Para cargar los productos de nuestra tienda desde la API REST de WooCommerce, necesitamos las claves relevantes dentro de nuestra aplicación. Para ello, podemos disponer de un archivo constans.js
.
Primero cree una carpeta llamada 'src' y cree subcarpetas dentro de la siguiente manera:
Ahora, generemos las claves para WooCommerce. En el panel de control de WordPress, vaya a WooCommerce → Configuración → API → Claves/Aplicaciones y haga clic en 'Agregar clave'.
A continuación, cree una clave de solo lectura con el nombre React Native. Copie la clave del consumidor y el secreto del consumidor en el archivo constants.js
de la siguiente manera:
const Constants = { URL: { wc: 'https://woocommerce-store.on-its-way.com/wp-json/wc/v2/' }, Keys: { ConsumerKey: 'CONSUMER_KEY_HERE', ConsumerSecret: 'CONSUMER_SECRET_HERE' } } export default Constants;
Comenzando con Reaccionar Navegación
React Navigation es una solución comunitaria para navegar entre las diferentes pantallas y es una biblioteca independiente. Permite a los desarrolladores configurar las pantallas de la aplicación React Native con solo unas pocas líneas de código.
Hay diferentes métodos de navegación dentro de React Navigation:
- Apilar,
- Cambiar,
- Pestañas,
- Cajón,
- y más.
Para nuestra aplicación, usaremos una combinación de StackNavigation
y DrawerNavigation
para navegar entre las diferentes pantallas. StackNavigation
es similar a cómo funciona el historial del navegador en la web. Estamos usando esto ya que proporciona una interfaz para el encabezado y los iconos de navegación del encabezado. Tiene push y pop similar a las pilas en las estructuras de datos. Empujar significa que agregamos una nueva pantalla en la parte superior de la pila de navegación. Pop elimina una pantalla de la pila.
El código muestra que StackNavigation
, de hecho, alberga DrawerNavigation
dentro de sí mismo. También toma propiedades para el estilo de encabezado y los botones de encabezado. Estamos colocando el botón del cajón de navegación a la izquierda y el botón del carrito de compras a la derecha. El botón del cajón enciende y apaga el cajón, mientras que el botón del carrito lleva al usuario a la pantalla del carrito de compras.
const StackNavigation = StackNavigator({ DrawerNavigation: { screen: DrawerNavigation } }, { headerMode: 'float', navigationOptions: ({ navigation, screenProps }) => ({ headerStyle: { backgroundColor: '#4C3E54' }, headerTintColor: 'white', headerLeft: drawerButton(navigation), headerRight: cartButton(navigation, screenProps) }) }); const drawerButton = (navigation) => ( <Text style={{ padding: 15, color: 'white' }} onPress={() => { if (navigation.state.index === 0) { navigation.navigate('DrawerOpen') } else { navigation.navigate('DrawerClose') } } }> ( <Text style={{ padding: 15, color: 'white' }} onPress={() => { navigation.navigate('CartPage') }} > <EvilIcons name="cart" size={30} /> {screenProps.cartCount} </Text> );
const StackNavigation = StackNavigator({ DrawerNavigation: { screen: DrawerNavigation } }, { headerMode: 'float', navigationOptions: ({ navigation, screenProps }) => ({ headerStyle: { backgroundColor: '#4C3E54' }, headerTintColor: 'white', headerLeft: drawerButton(navigation), headerRight: cartButton(navigation, screenProps) }) }); const drawerButton = (navigation) => ( <Text style={{ padding: 15, color: 'white' }} onPress={() => { if (navigation.state.index === 0) { navigation.navigate('DrawerOpen') } else { navigation.navigate('DrawerClose') } } }> ( <Text style={{ padding: 15, color: 'white' }} onPress={() => { navigation.navigate('CartPage') }} > <EvilIcons name="cart" size={30} /> {screenProps.cartCount} </Text> );
DrawerNavigation
, por otro lado, proporciona el cajón lateral que nos permitirá navegar entre Inicio, Tienda y Carrito. El DrawerNavigator
enumera las diferentes pantallas que el usuario puede visitar, a saber, la página de inicio, la página de productos, la página del producto y la página del carrito. También tiene una propiedad que tomará el contenedor del cajón: el menú deslizante que se abre al hacer clic en el menú de hamburguesas.
const DrawerNavigation = DrawerNavigator({ Home: { screen: HomePage, navigationOptions: { title: "RN WC Store" } }, Products: { screen: Products, navigationOptions: { title: "Shop" } }, Product: { screen: Product, navigationOptions: ({ navigation }) => ({ title: navigation.state.params.product.name }), }, CartPage: { screen: CartPage, navigationOptions: { title: "Cart" } } }, { contentComponent: DrawerContainer });
Inyectar la tienda Redux a App.js
Como estamos usando Redux en esta aplicación, tenemos que inyectar la tienda en nuestra aplicación. Hacemos esto con la ayuda del componente Provider
.
const store = configureStore(); class App extends React.Component { render() { return ( <Provider store={store}> <ConnectedApp /> </Provider> ) } }
Entonces tendremos un componente ConnectedApp
para que podamos tener el recuento del carrito en el encabezado.
class CA extends React.Component { render() { const cart = { cartCount: this.props.cart.length } return ( <StackNavigation screenProps={cart} /> ); } } function mapStateToProps(state) { return { cart: state.cart }; } const ConnectedApp = connect(mapStateToProps, null)(CA);
Redux Store, acciones y reductores
En Redux, tenemos tres partes diferentes:
- Tienda
Contiene el estado completo de toda su aplicación. La única forma de cambiar de estado es enviarle una acción. - Comportamiento
Un objeto simple que representa una intención de cambiar el estado. - reductores
Una función que acepta un estado y un tipo de acción y devuelve un nuevo estado.
Estos tres componentes de Redux nos ayudan a lograr un estado predecible para toda la aplicación. Para simplificar, veremos cómo se obtienen y guardan los productos en la tienda Redux.
En primer lugar, veamos el código para crear la tienda:
let middleware = [thunk]; export default function configureStore() { return createStore( RootReducer, applyMiddleware(...middleware) ); }
A continuación, la acción de productos es responsable de obtener los productos del sitio web remoto.
export function getProducts() { return (dispatch) => { const url = `${Constants.URL.wc}products?per_page=100&consumer_key=${Constants.Keys.ConsumerKey}&consumer_secret=${Constants.Keys.ConsumerSecret}` return axios.get(url).then(response => { dispatch({ type: types.GET_PRODUCTS_SUCCESS, products: response.data } )}).catch(err => { console.log(err.error); }) }; }
El reductor de productos es responsable de devolver la carga útil de datos y si es necesario modificarla.
export default function (state = InitialState.products, action) { switch (action.type) { case types.GET_PRODUCTS_SUCCESS: return action.products; default: return state; } }
Mostrando la tienda de WooCommerce
El archivo products.js
es nuestra página de Tienda. Básicamente muestra la lista de productos de WooCommerce.
class ProductsList extends Component { componentDidMount() { this.props.ProductAction.getProducts(); } _keyExtractor = (item, index) => item.id; render() { const { navigate } = this.props.navigation; const Items = ( <FlatList contentContainerStyle={styles.list} numColumns={2} data={this.props.products || []} keyExtractor={this._keyExtractor} renderItem={ ({ item }) => ( <TouchableHighlight style={{ width: '50%' }} onPress={() => navigate("Product", { product: item })} underlayColor="white"> <View style={styles.view} > <Image style={styles.image} source={{ uri: item.images[0].src }} /> <Text style={styles.text}>{item.name}</Text> </View> </TouchableHighlight> ) } /> ); return ( <ScrollView> {this.props.products.length ? Items : <View style={{ alignItems: 'center', justifyContent: 'center' }}> <Image style={styles.loader} source={LoadingAnimation} /> </View> } </ScrollView> ); } }
this.props.ProductAction.getProducts()
y this.props.products
son posibles gracias a mapStateToProps
y mapDispatchToProps
.
mapStateToProps
y mapDispatchToProps
State es la tienda Redux y Dispatch son las acciones que disparamos. Ambos se expondrán como accesorios en el componente.
function mapStateToProps(state) { return { products: state.products }; } function mapDispatchToProps(dispatch) { return { ProductAction: bindActionCreators(ProductAction, dispatch) }; } export default connect(mapStateToProps, mapDispatchToProps)(ProductsList);
Estilos
En React, los estilos nativos generalmente se definen en la misma página. Es similar a CSS, pero usamos propiedades camelCase
en lugar de propiedades separadas por guiones.
const styles = StyleSheet.create({ list: { flexDirection: 'column' }, view: { padding: 10 }, loader: { width: 200, height: 200, alignItems: 'center', justifyContent: 'center', }, image: { width: 150, height: 150 }, text: { textAlign: 'center', fontSize: 20, padding: 5 } });
Página de un solo producto
Esta página contiene detalles de un producto seleccionado. Muestra al usuario el nombre, precio y descripción del producto. También tiene la función 'Añadir al carrito'.
Página del carrito
Esta pantalla muestra la lista de artículos en el carrito. La acción tiene las funciones getCart
, addToCart
y removeFromCart
. El reductor maneja las acciones de la misma manera. La identificación de las acciones se realiza a través de actionTypes, constantes que describen la acción que se almacenan en un archivo separado.
export const GET_PRODUCTS_SUCCESS = 'GET_PRODUCTS_SUCCESS' export const GET_PRODUCTS_FAILED = 'GET_PRODUCTS_FAILED'; export const GET_CART_SUCCESS = 'GET_CART_SUCCESS'; export const ADD_TO_CART_SUCCESS = 'ADD_TO_CART_SUCCESS'; export const REMOVE_FROM_CART_SUCCESS = 'REMOVE_FROM_CART_SUCCESS';
Este es el código para el componente CartPage
:
class CartPage extends React.Component { componentDidMount() { this.props.CartAction.getCart(); } _keyExtractor = (item, index) => item.id; removeItem(item) { this.props.CartAction.removeFromCart(item); } render() { const { cart } = this.props; console.log('render cart', cart) if (cart && cart.length > 0) { const Items = <FlatList contentContainerStyle={styles.list} data={cart} keyExtractor={this._keyExtractor} renderItem={({ item }) => <View style={styles.lineItem} > <Image style={styles.image} source={{ uri: item.image }} /> <Text style={styles.text}>{item.name}</Text> <Text style={styles.text}>{item.quantity}</Text> <TouchableOpacity style={{ marginLeft: 'auto' }} onPress={() => this.removeItem(item)}><Entypo name="cross" size={30} /></TouchableOpacity> </View> } />; return ( <View style={styles.container}> {Items} </View> ) } else { return ( <View style={styles.container}> <Text>Cart is empty!</Text> </View> ) } } }
Como puede ver, estamos usando una FlatList
para iterar a través de los artículos del carrito. Toma una matriz y crea una lista de elementos que se mostrarán en la pantalla.
Conclusión
Puede configurar información sobre la aplicación, como el nombre y el icono, en el archivo app.json
. La aplicación se puede publicar después de que npm instale exp.
Para resumir:
- Ahora tenemos una aplicación de comercio electrónico decente con React Native;
- Expo se puede utilizar para ejecutar el proyecto en un teléfono inteligente;
- Se pueden utilizar las tecnologías de back-end existentes, como WordPress;
- Redux se puede usar para administrar el estado de toda la aplicación;
- Los desarrolladores web, especialmente los desarrolladores de React, pueden aprovechar este conocimiento para crear aplicaciones más grandes.
Para la aplicación completa, puede visitar mi proyecto en Github y clonarlo. Siéntase libre de bifurcarlo y mejorarlo aún más. Como ejercicio, puede continuar creando más funciones en el proyecto, como:
- página de pago,
- Autenticación,
- Almacenar los datos del carrito en AsyncStorage para que al cerrar la aplicación no se borre el carrito.