Criando aplicativos móveis usando React Native e WordPress
Publicados: 2022-03-10Como desenvolvedores da Web, você pode ter pensado que o desenvolvimento de aplicativos móveis exige uma nova curva de aprendizado com outra linguagem de programação. Talvez Java e Swift precisem ser adicionados ao seu conjunto de habilidades para começar a funcionar com iOS e Android, e isso pode atrapalhar você.
Mas este artigo tem uma surpresa! Analisaremos a criação de um aplicativo de comércio eletrônico para iOS e Android usando a plataforma WooCommerce como nosso back-end. Este seria um ponto de partida ideal para qualquer pessoa disposta a entrar no desenvolvimento multiplataforma nativo.
Uma breve história do desenvolvimento multiplataforma
Estamos em 2011 e vemos o início do desenvolvimento de aplicativos móveis híbridos. Frameworks como Apache Cordova, PhoneGap e Ionic Framework surgem lentamente. Tudo parece bem, e os desenvolvedores da Web estão codificando avidamente aplicativos móveis com seu conhecimento existente.
No entanto, os aplicativos móveis ainda pareciam versões móveis de sites. Nenhum design nativo como o material design do Android ou a aparência plana do iOS. A navegação funcionou de forma semelhante à web e as transições não foram suaves. Os usuários não estavam satisfeitos com os aplicativos criados usando a abordagem híbrida e sonhavam com a experiência nativa.
Avanço rápido para março de 2015, e React Native aparece em cena. Os desenvolvedores são capazes de construir aplicativos multiplataforma verdadeiramente nativos usando React, uma biblioteca JavaScript favorita para muitos desenvolvedores. Eles agora podem aprender facilmente uma pequena biblioteca além do que sabem com JavaScript. Com esse conhecimento, os desenvolvedores agora estão mirando na web, iOS e Android.
Além disso, as alterações feitas no código durante o desenvolvimento são carregadas nos dispositivos de teste quase instantaneamente! Isso costumava levar vários minutos quando tínhamos desenvolvimento nativo por meio de outras abordagens. Os desenvolvedores podem aproveitar o feedback instantâneo que costumavam adorar no desenvolvimento da web.
Os desenvolvedores do React estão mais do que felizes em poder usar os padrões existentes que eles seguiram em uma nova plataforma. Na verdade, eles estão visando mais duas plataformas com o que eles já conhecem muito bem.
Tudo isso é bom para o desenvolvimento front-end. Mas que opções temos para a tecnologia de back-end? Ainda temos que aprender uma nova linguagem ou framework?
A API REST do WordPress
No final de 2016, o WordPress lançou a tão esperada API REST em seu núcleo e abriu as portas para soluções com back-ends desacoplados.
Portanto, se você já possui um site WordPress e WooCommerce e deseja manter exatamente as mesmas ofertas e perfis de usuário em seu site e aplicativo nativo, este artigo é para você!
Suposições feitas neste artigo
Vou orientá-lo usando sua habilidade do WordPress para criar um aplicativo móvel com uma loja WooCommerce usando React Native. O artigo pressupõe:
- Você está familiarizado com as diferentes APIs do WordPress, pelo menos em um nível iniciante.
- Você está familiarizado com o básico do React.
- Você tem um servidor de desenvolvimento WordPress pronto. Eu uso Ubuntu com Apache.
- Você tem um dispositivo Android ou iOS para testar com a Expo.
O que vamos construir neste tutorial
O projeto que vamos construir através deste artigo é um aplicativo de loja de moda. O aplicativo terá as seguintes funcionalidades:
- Página da loja listando todos os produtos,
- Página de produto única com detalhes do item selecionado,
- Recurso 'Adicionar ao carrinho',
- Recurso 'Mostrar itens no carrinho',
- Recurso 'Remover item do carrinho'.
Este artigo tem como objetivo inspirá-lo a usar este projeto como ponto de partida para criar aplicativos móveis complexos usando React Native.
Nota : Para o aplicativo completo, você pode visitar meu projeto no Github e cloná-lo .
Iniciando nosso projeto
Começaremos a construir o aplicativo de acordo com a documentação oficial do React Native. Tendo instalado o Node em seu ambiente de desenvolvimento, abra o prompt de comando e digite o seguinte comando para instalar o Create React Native App globalmente.
npm install -g create-react-native-app
Em seguida, podemos criar nosso projeto
create-react-native-app react-native-woocommerce-store
Isso criará um novo projeto React Native que podemos testar com a Expo.
Em seguida, precisaremos instalar o aplicativo Expo em nosso dispositivo móvel que queremos testar. Está disponível para iOS e Android.
Ao instalar o aplicativo Expo, podemos executar o npm start em nossa máquina de desenvolvimento.
cd react-native-woocommerce-store npm start
Depois disso, você pode escanear o código QR através do aplicativo Expo ou inserir o URL fornecido na barra de pesquisa do aplicativo. Isso executará o aplicativo básico 'Hello World' no celular. Agora podemos editar o App.js para fazer alterações instantâneas no aplicativo executado no telefone.
Como alternativa, você pode executar o aplicativo em um emulador. Mas para brevidade e precisão, abordaremos a execução em um dispositivo real.
Em seguida, vamos instalar todos os pacotes necessários para o aplicativo usando este comando:
npm install -s axios react-native-htmlview react-navigation react-redux redux redux-thunk
Configurando um site WordPress
Como este artigo trata da criação de um aplicativo React Native, não entraremos em detalhes sobre como criar um site WordPress. Consulte este artigo sobre como instalar o WordPress no Ubuntu. Como a API REST do WooCommerce requer HTTPS, verifique se ela está configurada usando Let's Encrypt. Consulte este artigo para obter um guia prático.
Não estamos criando uma instalação do WordPress no localhost, pois executaremos o aplicativo em um dispositivo móvel e também porque o HTTPS é necessário.
Depois que o WordPress e o HTTPS forem configurados com sucesso, podemos instalar o plug-in WooCommerce no site.
Depois de instalar e ativar o plugin, continue com a configuração da loja WooCommerce seguindo o assistente. Após a conclusão do assistente, clique em 'Retornar ao painel'.
Você será saudado por outro prompt.
Clique em 'Vamos' para 'Adicionar produtos de exemplo'. Isso nos poupará tempo para criar nossos próprios produtos para exibir no aplicativo.
Arquivo de Constantes
Para carregar os produtos da nossa loja a partir da API REST do WooCommerce, precisamos das chaves relevantes em nosso aplicativo. Para isso, podemos ter um arquivo constans.js
.
Primeiro crie uma pasta chamada 'src' e crie subpastas dentro da seguinte forma:
Agora, vamos gerar as chaves para WooCommerce. No painel do WordPress, navegue até WooCommerce → Configurações → API → Chaves/Aplicativos e clique em 'Adicionar chave'.
Em seguida, crie uma chave Read Only com o nome React Native. Copie a chave do consumidor e o segredo do consumidor para o arquivo constants.js
da seguinte maneira:
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;
Começando com React Navigation
O React Navigation é uma solução comunitária para navegar entre as diferentes telas e é uma biblioteca independente. Ele permite que os desenvolvedores configurem as telas do aplicativo React Native com apenas algumas linhas de código.
Existem diferentes métodos de navegação dentro do React Navigation:
- Pilha,
- Trocar,
- Abas,
- Gaveta,
- e mais.
Para nosso aplicativo, usaremos uma combinação de StackNavigation
e DrawerNavigation
para navegar entre as diferentes telas. StackNavigation
é semelhante ao funcionamento do histórico do navegador na web. Estamos usando isso porque ele fornece uma interface para o cabeçalho e os ícones de navegação do cabeçalho. Tem push e pop semelhantes a pilhas em estruturas de dados. Push significa que adicionamos uma nova tela ao topo da Pilha de Navegação. Pop remove uma tela da pilha.
O código mostra que o StackNavigation
, na verdade, abriga o DrawerNavigation
dentro de si. Também recebe propriedades para o estilo do cabeçalho e os botões do cabeçalho. Estamos colocando o botão da gaveta de navegação à esquerda e o botão do carrinho de compras à direita. O botão da gaveta liga e desliga a gaveta, enquanto o botão do carrinho leva o usuário para a tela do carrinho 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 outro lado, fornece a gaveta lateral que nos permitirá navegar entre Home, Shop e Cart. O DrawerNavigator
lista as diferentes telas que o usuário pode visitar, ou seja, página inicial, página de produtos, página de produto e página de carrinho. Ele também tem uma propriedade que vai pegar o container da Gaveta: o menu deslizante que se abre ao clicar no menu do hambúrguer.
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 });
Injetando a Redux Store no App.js
Como estamos usando o Redux neste aplicativo, temos que injetar a loja em nosso aplicativo. Fazemos isso com a ajuda do componente Provider
.
const store = configureStore(); class App extends React.Component { render() { return ( <Provider store={store}> <ConnectedApp /> </Provider> ) } }
Teremos então um componente ConnectedApp
para que possamos ter a contagem do carrinho no cabeçalho.
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);
Loja Redux, Ações e Redutores
No Redux, temos três partes diferentes:
- Armazenar
Mantém todo o estado de todo o seu aplicativo. A única maneira de alterar o estado é despachar uma ação para ele. - Ações
Um objeto simples que representa uma intenção de alterar o estado. - Redutores
Uma função que aceita um estado e um tipo de ação e retorna um novo estado.
Esses três componentes do Redux nos ajudam a alcançar um estado previsível para todo o aplicativo. Para simplificar, veremos como os produtos são obtidos e salvos na loja Redux.
Antes de mais nada, vamos ver o código para criar a loja:
let middleware = [thunk]; export default function configureStore() { return createStore( RootReducer, applyMiddleware(...middleware) ); }
Em seguida, a ação de produtos é responsável por buscar os produtos do site 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); }) }; }
O redutor de produtos é responsável por retornar a carga útil de dados e se ela precisa ser modificada.
export default function (state = InitialState.products, action) { switch (action.type) { case types.GET_PRODUCTS_SUCCESS: return action.products; default: return state; } }
Exibindo a loja WooCommerce
O arquivo products.js
é nossa página da Loja. Ele basicamente exibe a lista de produtos do 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()
e this.props.products
são possíveis devido a mapStateToProps
e mapDispatchToProps
.
mapStateToProps
e mapDispatchToProps
State é a loja Redux e Dispatch são as ações que disparamos. Ambos serão expostos como adereços no componente.
function mapStateToProps(state) { return { products: state.products }; } function mapDispatchToProps(dispatch) { return { ProductAction: bindActionCreators(ProductAction, dispatch) }; } export default connect(mapStateToProps, mapDispatchToProps)(ProductsList);
Estilos
No React, os estilos nativos geralmente são definidos na mesma página. É semelhante ao CSS, mas usamos propriedades camelCase
em vez de propriedades hifenizadas.
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 produto única
Esta página contém detalhes de um produto selecionado. Ele mostra ao usuário o nome, preço e descrição do produto. Ele também tem a função 'Adicionar ao carrinho'.
Página do carrinho
Esta tela mostra a lista de itens no carrinho. A ação tem as funções getCart
, addToCart
e removeFromCart
. O redutor lida com as ações da mesma forma. A identificação das ações é feita através de actionTypes — constantes que descrevem a ação que são armazenadas em um arquivo 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 é o código para o 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 você pode ver, estamos usando um FlatList
para percorrer os itens do carrinho. Ele recebe uma matriz e cria uma lista de itens a serem exibidos na tela.
Conclusão
Você pode configurar informações sobre o aplicativo, como nome e ícone, no arquivo app.json
. O aplicativo pode ser publicado após a instalação do npm exp.
Resumindo:
- Agora temos um aplicativo de comércio eletrônico decente com React Native;
- A Expo pode ser usada para executar o projeto em um smartphone;
- Tecnologias de back-end existentes, como WordPress, podem ser usadas;
- O Redux pode ser usado para gerenciar o estado de todo o aplicativo;
- Os desenvolvedores da Web, especialmente os desenvolvedores do React, podem aproveitar esse conhecimento para criar aplicativos maiores.
Para o aplicativo completo, você pode visitar meu projeto no Github e cloná-lo. Sinta-se à vontade para bifurcá-lo e melhorá-lo ainda mais. Como exercício, você pode continuar criando mais recursos no projeto, como:
- página de checkout,
- Autenticação,
- Armazenar os dados do carrinho no AsyncStorage para que o fechamento do aplicativo não limpe o carrinho.