-
Notifications
You must be signed in to change notification settings - Fork 3
React Native Tutorial
React Native é um Framework Javascript desenvolvido pelo Facebook para construção de Apps mobile nativos. Ele faz uso do Framework React e oferece uma grande quantidade de componentes e API's.
Neste tutorial iremos fazer um App simples para registro e visualizações de tarefas, utilizando dos recursos disponibilizados pelo React Native e com o serviço Cloud Firestore.
Primeiro é necessário ter todo o ambiente configurado para poder construir o App. Siga o tutorial dessa wiki, para fazer a configuração do seu ambiente.
Para começar é necessário primeiro que você faça o clone do seguinte repositório: https://github.com/netochaves/TodoDemo neste repositório terá os arquivos iniciais para o projeto. Feito o clone do repositório, abra a pasta do projeto com um terminal e digite o seguinte comando:
npm install
Este comando irá instalar todos os módulos necessários para o projeto.
Agora abra o projeto com o seu editor de texto ou IDE, crie um novo arquivo Todos.js
na raiz do projeto, agora no arquivo index.js
altere para que ele aponte para o novo arquivo criado
import { AppRegistry } from "react-native"
import Todos from "./Todos"
import { name as appName } from "./app.json"
AppRegistry.registerComponent(appName, () => Todos)
Aqui estou importando o arquivo Todos, e colocando para que ele seja mostrado quando o App inicializar.
Agora configure uma classe js basica no Todos.js
import React from 'react';
class Todos extends React.Component {
render() {
return null;
}
}
export default Todos;
render()
é o método que renderiza a tela cada vez que seu estado muda, por enquanto não estamos renderizando nada.
O Cloud Firestore permite que documentos (Objetos de data) sejam registrados em coleções. Nosso Todo App vai ter apenas uma lista de todos, esses todos serão armazenados em uma coleção de "todos" no Firestore. Cada documento representa um todo e terá os seus dados, no nosso caso apenas o titulo e o status ("complete").
O primeiro passo é criar uma referência para a coleção, que pode ser usado dentro do nosso componente para enviar requisições e receber respostas. Vamos importar o react-native-firebase
e criar essa referência no construtor do componente.
import React from 'react';
import firebase from 'react-native-firebase';
class Todos extends React.Component {
constructor() {
super();
this.ref = firebase.firestore().collection('todos');
}
...
Para não longar muito esse tutorial iremos utilizar styles in-line mas você deve utilizar StyleSheet para os seus aplicativos.
A UI vai ser simples: uma scrollable list de todos e um textInput com um Button para adicionar novos todos. Vamos adicionar nossa UI ao método render()
render() {
return (
<View>
<ScrollView>
<Text>List of TODOs</Text>
</ScrollView>
<TextInput
placeholder={'Add TODO'}
/>
<Button
title={'Add TODO'}
disabled={true}
onPress={() => {}}
/>
</View>
);
}
É necessário que se faça os imports dos componentes utilizados na UI, portanto nas primeiras linhas do arquivo, adicione:
import { ScrollView, View, Text, TextInput, Button } from 'react-native'
Com isso rode o comando react-native run-android
e você deverá ver uma tela como a seguinte:
Agora precisamos pegar o texto digitado no textInput
para que possamos enviar o valor para o Cloud Firestore quando o botão for pressionado.
Adicione o state para o construtor:
constructor() {
super();
this.ref = firebase.firestore().collection('todos');
this.state = {
textInput: '',
};
}
Adicione o método updateTextInput()
para atualizar o state quando o valor de textInput
for alterado
updateTextInput(value) {
this.setState({ textInput: value });
}
Adicione as seguintes propriedades no TextInput
para que quando o seu valor for alterado acione o metodo updateTextInput()
<TextInput
placeholder={'Add TODO'}
value={this.state.textInput}
onChangeText={(text) => this.updateTextInput(text)}
/>
Mude o valor da propriedade disabled
para que o botão seja ativado baseado no valor do campo textInput
<Button
title={'Add TODO'}
disabled={!this.state.textInput.length}
onPress={() => {}}
/>
Seu App agora deve responder as mudanças no texto:
Para adicionar um novo documento para a coleção, nós podemos chamar o método add na referência da coleção. Vamos criar um método addTodo()
para adicionar o todo.
addTodo() {
this.ref.add({
title: this.state.textInput,
complete: false,
});
this.setState({
textInput: '',
});
}
Vamos configurar o botão para acionar o método
<Button
title={'Add TODO'}
disabled={!this.state.textInput.length}
onPress={() => this.addTodo()}
/>
Quando o botão é pressionado o novo todo é enviado ao Cloud Firestore e adicionado na coleção. Então é resetado o valor de TextInput
no state
. O método add é assincrono e retorna uma Referência de Documento de uma promise se requerido.
O novo documento adicionado no Cloud Firestore
Já conseguimos adicionar todos a nossa coleção, mas agora precisamos mostrar esses todos na tela do App. Cloud firestore oferece dois métodos para isso, get()
que retorna os documentos de uma vez e onSnapshot()
que fornece autalizações em tempo real quando um documento é alterado na coleção (adição, remoção e update). Para o nosso TODO App, nós queremos resultados em tempo real, então vamos implementar isso.
Adicione um loading
e todos
ao componente.
constructor() {
super();
this.ref = firebase.firestore().collection('todos');
this.unsubscribe = null;
this.state = {
textInput: '',
loading: true,
todos: [],
};
}
Nós precisamos de um loading
para indicar para o usuário que a primeira conexão com o Cloud Firestore ainda não foi completada. Também adicionamos um unsubscribe
atributo ao state
que iremos ver o uso mais a frente.
Agora, iremos criar o método que fica escutando por alterações e fazer a iteração em cada documento, esse método ficará dentro do método de ciclo de vida componentDidMount()
, este método será acionado toda vez que o componente for montado e isso acontece a cada vez que o state
é atualizado. Para saber mais sobre os métodos de ciclo de vida, veja: https://reactjs.org/docs/state-and-lifecycle.html
componentDidMount() {
this.unsubscribe = this.ref.onSnapshot(querySnapshot => {
const todos = []
querySnapshot.forEach(doc => {
const { title, complete } = doc.data()
todos.push({
key: doc.id,
doc,
title,
complete
})
})
this.setState({ todos, loading: false })
})
}
Utilizamos o Snapshot método forEach
para iterar sobre cada documento na ordem que eles são armazenados no Cloud Firestore, guardamos o ID (.id) e os dados (.data) do documento, também guardamos o DocumentSnapshot
no state para acessar isso diretamente.
Toda vez que um documento for adicionado, alterado ou removido esse método será atualizado e irá atualizar o state
da aplicação.
Agora que possuimos os todos carregados no state
iremos exibi-los na tela. Para isso utilizaremos do componente FlatList pois o ScrollView pode causar problemas de performance.
Atualizando o loading
render() {
if (this.state.loading) {
return null; // or render a loading icon
}
Exibe os todos em uma FlatList
usando o todos
state.
import { FlatList, Button, View, Text, TextInput } from 'react-native';
import Todo from './Todo'; // we'll create this next
...
render() {
if (this.state.loading) {
return null
}
return (
<View style={{ flex: 1 }}>
<FlatList
data={this.state.todos}
renderItem={({ item }) => <Todo {...item} />}
/>
<TextInput
placeholder={'Add TODO'}
value={this.state.textInput}
onChangeText={(text) => this.updateTextInput(text)}
/>
<Button
title={'Add TODO'}
disabled={!this.state.textInput.length}
onPress={() => this.addTodo()}
/>
</View>
)
}
Você pode perceber que estamos renderizando um componente Todo para cada item, abaixo estará o código desse componente, percebe-se também que este componente é um PureComponent
que fornecerá uma grande melhoria de performance pois só será atualizado quando os valores de title e/ou complete serem alterados.
crie o arquivo Todo.js
na raiz do projeto:
import React from 'react';
import { TouchableHighlight, View, Text } from 'react-native';
export default class Todo extends React.PureComponent {
// toggle a todo as completed or not via update()
toggleComplete() {
this.props.doc.ref.update({
complete: !this.props.complete,
});
}
render() {
return (
<TouchableHighlight
onPress={() => this.toggleComplete()}
>
<View style={{ flex: 1, height: 48, flexDirection: 'row', alignItems: 'center' }}>
<View style={{ flex: 8 }}>
<Text>{this.props.title}</Text>
</View>
<View style={{ flex: 2 }}>
{this.props.complete && (
<Text>COMPLETE</Text>
)}
</View>
</View>
</TouchableHighlight>
)
}
}
Este componente apenas exibe o titulo do todo e se ele está completo ou não. Ele está dentro de um componente TouchableHighlight
que irá criar um efeito quando o componente for selecionado, ao acionar o componente podemos pegar a referência do documento diretamente da propriedade doc
que foi passada anteriormente e atualizar esse documento utilizando do método update
(Que também é assíncrono caso você queira tratar erros).
Agora podemos selecionar um todo, para mudar o seu estado para completo ou remover esse estado, e isso é mostrado em tempo real para o usuário, pois nosso método subscription
atualiza o state
toda vez que houver uma alteração no Cloud Firestore, cool right?
Isso é apenas 1% do que o react-native pode fazer junto com o Firebase para os seus Apps. Deixarei alguns links abaixo caso você queira continuar se aventurando nesse mundo do React-native. Let's Code!!
React native official docs - https://facebook.github.io/react-native/docs/getting-started
React native course - Free - https://www.youtube.com/watch?v=frvXANSaSec
React native guide - https://www.reactnative.guide
Code Camp - https://www.freecodecamp.org