Buscar

Roteiro_FormularioComLista_Parte2

Prévia do material em texto

PONTIFÍCIA UNIVERSIDADE CATÓLICA DE MINAS GERAIS
Curso : Tecnologia em Análise e Desenvolvimento de Sistemas
Disciplina: : Desenvolvimento Web Full Stack
Professora : Sinaide Bezerra
Roteiro para prática em laboratório
Intruções:
Atividade individual
Objetivo:
Gerar de um formulário com lista de material contato com o uso de React Native.
Ferramenta de desenvolvimento:
Snack - React Native in the browser – Expo - https://snack.expo.dev
Roteiro:
A partir do código disponível no arquivo listamaterial_v1.zip efetue as seguintes alterações:
Estados do formulário
Vamos programar os estados dos campos, para que seus valores sejam armazenados em 
memória quando o usuário digitar neles.
Importe a a função useState do React no AppForm.js.
import React, {useState} from 'react';
Crie os objetos de estado e as funções de manipulação do estado interno à function AppForm, 
antes do return..
export default function AppForm({ navigation }) {
 
const [descricao, setDescricao] = useState(''); 
const [quantidade, setQuantidade] = useState('');
 
function handleDescriptionChange(descricao){
setDescricao(descricao); } 
function handleQuantityChange(quantidade){
setQuantidade(quantidade); }
function handleButtonPress(){ 
  console.log({id: new Date().getTime(), descricao, quantidade}); 
  navigation.navigate("AppList");
}
https://snack.expo.dev/
Discuta com outros integrantes o que significa cada linha do código.
Responda:
O que acontece com está declaração e por quê? {id: new Date().getTime(), ...}
O que vai acontecer com o comando: navigation.navigate("AppList");
Referencie as funções de manipulação de estado nas propriedades onChangeText dos inputs e 
onPress do botão.
<TextInput 
  style={styles.input} 
  onChangeText={handleDescriptionChange} 
  placeholder="O que está faltando em casa?"
  clearButtonMode="always" /> 
<TextInput 
  style={styles.input} 
  onChangeText={handleQuantityChange} 
  placeholder="Digite a quantidade" 
  keyboardType={'numeric'}
  clearButtonMode="always" /> 
<TouchableOpacity style={styles.button} onPress={handleButtonPress}> 
  <Text style={styles.buttonText}>Salvar</Text> 
</TouchableOpacity>
Atualize e teste a aplicação.
Salvando no banco de dados local
Os dados capturados pelos estados irão ser salvos no banco de dados local do dispositivo.
Altere os imports do AppForm.js.
import React, {useState} from 'react';
import { StatusBar } from 'expo-status-bar';
import { StyleSheet, Text, View, TextInput, TouchableOpacity } from 'react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';
Altere a função handleButtonPress para salvar os dados obtidos no nosso banco de dados
async function handleButtonPress(){ 
  const listItem = {id: new Date().getTime(), descricao, quantidade: parseInt(quantidade)};
  let savedItems = [];
  const response = await AsyncStorage.getItem('items');
  
  if(response) savedItems = JSON.parse(response);
  savedItems.push(listItem);
 
  await AsyncStorage.setItem('items', JSON.stringify(savedItems));
  navigation.navigate("AppList", listItem);
}
Discuta com colegas o que significa cada linha do código.
 O que faz o comando await?
Criando a listagem
Crie o compontente AppItem.js para receber a listagem armazenada no banco de dados da 
seguinte forma:
import React from 'react';
import {StyleSheet, Text, View, TouchableOpacity} from 'react-native';
 
export default function AppItem(props){
    return (
        <View style={styles.container}>
          <Text style={styles.textItem}>{props.item}</Text>
          <View style={styles.buttonsContainer}>
            <TouchableOpacity style={styles.deleteButton} > 
                <Text style={styles.buttonText}>X</Text> 
            </TouchableOpacity> 
            <TouchableOpacity style={styles.editButton} > 
                <Text style={styles.buttonText}>Editar</Text> 
            </TouchableOpacity> 
          </View>
        </View>
      );
}
A função recebe um objeto props que conterá o texto do item a ser adicionado na listagem. 
Associe os estilos a seguir ao AppItem.js.
const styles = StyleSheet.create({
    container: {
      backgroundColor: '#fff',
      marginTop: 20,
      width: '100%'
    },
    buttonsContainer: {
        flexDirection: 'row-reverse',
        alignItems: 'flex-end',
        borderBottomWidth: 1,
        borderBottomColor: '#CCC',
        paddingBottom: 10,
        marginTop: 10,
    },
    editButton: {
        marginLeft: 10,
        height: 40,
        backgroundColor: 'blue',
        borderRadius: 10,
        padding: 10,
        fontSize: 12,
        elevation: 10,
        shadowOpacity: 10,
        shadowColor: '#ccc',
        alignItems: 'center'
    },
    deleteButton: {
        marginLeft: 10,
        height: 40,
        width: 40,
        backgroundColor: 'red',
        borderRadius: 10,
        padding: 10,
        fontSize: 12,
        elevation: 10,
        shadowOpacity: 10,
        shadowColor: '#ccc',
        alignItems: 'center'
    },
    buttonText: {
        color: '#fff',
        fontWeight: 'bold',
    },
    textItem: {
        fontSize: 20,
    }
  });
Construa a lista no módulo AppList.js.
Altere os imports para:
import { StatusBar } from 'expo-status-bar';
import React, {useState} from 'react';
import { StyleSheet, View, Text, ScrollView } from 'react-native';
import AppItem from './AppItem';
Teste a lista com valores estáticos. Adicione ao componente:
const [items, setItems] = useState([
 {id: 1, quantidade: 5, descricao: "canetas" }, 
 {id: 2, quantidade: 1, descricao: "caderno" }, 
 {id: 3, quantidade: 0.5, descricao: "metro de fita" }, 
 {id: 4, quantidade: 1, descricao: "pincel" }, 
]);
Adicione uma ScrollView (área com rolagem):
1
2
3
4
5
6
7
8
9
10
11
12
13
return (
<View style={styles.container}>
    <StatusBar style="light" />
    <Text style={styles.title}>Lista de Compras</Text>
    <ScrollView 
        style={styles.scrollContainer}
        contentContainerStyle={styles.itemsContainer}>
        { items.map(item => {
            return <AppItem key={item.id} id={item.id} item={item.quantidade + ' de ' + 
item.descricao} />
        }) }
    </ScrollView>
</View>
);
A que se refere a contentContainerStyle?
O que faz o items.map?
Adicione os estilos a seguir:
const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#D93600',
    alignItems: 'center',
    justifyContent: 'center'
  },
  title: {
    color: '#fff',
    fontSize: 20,
    fontWeight: 'bold',
    marginTop: 50,
    marginBottom: 20
  },
  scrollContainer: {
    flex: 1,
    width: '90%'
  },
  itemsContainer: {
    flex: 1,
    marginTop: 10,
    padding: 20,
    borderTopLeftRadius: 10,
    borderTopRightRadius: 10,
    alignItems: 'stretch',
    backgroundColor: '#fff'
  },
});
Resultado esperado:
.
Refatorando o acesso a dados
Crie um arquivo Database.js e adicione a lógica de acesso aos dados.
Adicione o import:
import AsyncStorage from '@react-native-async-storage/async-storage';
 
Adicione a função:
async function saveItem(listItem){
    listItem.id = new Date().getTime();
    let savedItems = [];
    const response = await AsyncStorage.getItem('items');
    
    if(response) savedItems = JSON.parse(response);
    savedItems.push(listItem);
    
    return AsyncStorage.setItem('items', JSON.stringify(savedItems));
}
 
module.exports = {
    saveItem
}
No arquivo AppForm.js, import o módulo Database e altere a função handleButtonPress .
import Database from './Database';
async function handleButtonPress(){ 
  const listItem = {descricao, quantidade: parseInt(quantidade)};
  Database.saveItem(listItem)
    .then(response => navigation.navigate("AppList", listItem));
}
Retornando os itens do banco de dados
No módulo Database.js adicionar a function.
function getItems(){
    return AsyncStorage.getItem('items')
            .then(response => {
                if(response)
                    return Promise.resolve(JSON.parse(response));else
                    return Promise.resolve([]);
            })
}
Basicamente ela pega todos os itens do AsyncStorage e retorna em forma de array através de 
uma promise. 
https://www.luiztools.com.br/post/programacao-assincrona-em-nodejs-callbacks-e-promises/
No final do arquivo adicione o module.exports.
module.exports = {
    saveItem,
    getItems
}
Pesquise o que faz um promisse.
No arquivo AppList adicione o useEffect e o Database. Veja os imports a seguir:
import { StatusBar } from 'expo-status-bar';
import React, {useState, useEffect} from 'react';
import { StyleSheet, View, Text, ScrollView } from 'react-native';
import AppItem from './AppItem';
import Database from './Database';
Altere a assinatura da função para que decomponha em dois objetos, um route e um 
navigation.
export default function AppList({ route, navigation }) 
O navigation é utilizado para trocar de tela. O route, são os parâmetrosS de navegação que 
trouxeram até esta tela. 
Altere o useState que estava com valores pré-defindos para que sejam obtidos do banco de 
dados.
const [items, setItems] = useState([]);
  
  useEffect(() => {
      Database.getItems().then(items => setItems(items));
  }, [route]);
O useEffect dispara todas as vezes que a variável route é alterada.
Teste a aplicação.
	Estados do formulário
	Salvando no banco de dados local
	Refatorando o acesso a dados
	Crie um arquivo Database.js e adicione a lógica de acesso aos dados.
	
	Adicione a função:
	Retornando os itens do banco de dados

Continue navegando