Criando uma TodoList com React Native
Tags: reactnative, beginners, programming
Published: 2023-04-10 19:43:21

Com o React Native, conseguimos criar diversas aplicações mobile para diferentes tipos de plataforma seja Android ou iOS. Uma das funcionalidades comuns em muitos aplicativos móveis é uma lista de tarefas, também chamada TodoList. Neste artigo, vamos aprender a criar uma TodoList em React Native.

**Iniciando o projeto TodList-**

Antes de tudo, é necessário criar um diretório para o nosso projeto, para isso usamos o seguinte comando, pois com ele iremos começar nossa aplicação:

```
npx create-expo-app -t expo-template-blank-typescript
```

Após isso ele irá perguntar qual será o nome do projeto, o qual daremos o nome de: Desafio.

Feito isso temos nosso projeto e nele podemos separar nossos arquivos que iremos usar da seguinte maneira:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/odlp24zgaqxo2tnqvfrh.png)

Seguindo o caminho `Screens/Home/index.tsx` podemos inserir nosso código para a TodoList.


Nosso código inicia fazendo as importações de `useState` para controlar o estado de mudança de nosso TodoList, também importamos ( View , Text, TextInput, TouchableOpacity, FlatList, Alert, Image) do react. Fazemos também uma importação de estilização da qual não iremos inserir neste código, mas será utilizada via StyleSheet. Também vamos importar um componente reservado para tarefas, chamado `Tarefas`. Ele ficará da seguinte maneira:

```
import React, {useState} from "react";

import { View , Text, TextInput, TouchableOpacity, FlatList, Alert, Image} from 'react-native';

import { styles } from "./style";

import { Tarefas} from "../../components/Tarefas"
```


Com todas as importações feitas, começamos a criar nossa exportação da função Home(que iremos passar como componente, no App.tsx), que não apresenta parâmetros mas tem diversas consts de controle de estado:

```
 const [taskName , setTaskName] = useState('');
 const [tasks , setTask] = useState <String[]> ([]);
 const [isDarkMode, setIsDarkMode] = useState(false);
```

A primera const, com useState `taskName` é onde será passado nossas tarefas. `task` servirá para listar nossas tarefas, e `isDarkMode` servirá para criar um "modo escuro" simples que irá trocar apenas o seu papel de parede.

Logo após, criamos a função `handleTaskAdd` para controlar resultados de envio da tarefa. Criamos uma const `taskLowerCase` que irá percorrer a listagem `task` por meio de `.map` convertendo qualquer informação escrita no campo de envio, para lowerCase(ou seja, converter todas as letras alfabéticas em strings minúsculas). Se ele perceber que a tarefa passada já está incluída, ou seja, já existe, retornaremos uma caixa de alerta com a mensagem: Tarefa existe, Essa tarefa já existe na lista.

E caso o `taskName` que é onde estamos escrevendo as tarefas, seja igual a 0, ou seja,não tenha nada escrito em seu TextInput(iremos falar mais a frente sobre o local que ficará armazenado o `taskName`), retornará uma mensagem de alerta revelando o espaço vazio. Finalizando, temos um `setTask` que  serve para atualizar o estado da listagem de tarefas. Usamos o operador spread,que são os três pontos(...) criando um novo array onde inclui todos os valores anteriores e o novo valor adicionado, que é o `taskName`, e o `setTaskName ('')` ao final significa que  é para limpar o valor do campo de entrada de texto ou outro elemento do formulário, para que o usuário possa inserir um novo valor.

```
function handleTaskAdd() {
      
      const taskLowerCase = tasks.map(task => task.toLowerCase())
      if (taskLowerCase.includes(taskName.toLowerCase())) {
        return Alert.alert("Tarefa existe", "Essa tarefa já existe na lista");
      }
      
      if (taskName.length === 0) {
        return Alert.alert("Espaço vazio", "Nenhuma tarefa foi digitada");

      }
      setTask( previewState => [...previewState ,taskName]);
      setTaskName ('');

    }
```

Partimos para o `handleTaskRemove` que irá controlar a exclusão das tarefas, e caso clique no botão de excluir, ele irá apresentar um alerta de perguntando se desejo ou não remover a tarefa. O mesmo será para `toggleDarkMode`.

```
function handleTaskRemove(name: string) {
      Alert.alert("Remover",`Remover tarefa: ${name}?`,
      [
        {
          text: "SIM",
          onPress: () => setTask(previewState => previewState.filter(task => task !== name))
        },
        {
          text:"NÃO",
          style: "cancel"
        }
      ])
    }

    function toggleDarkMode() {
      setIsDarkMode(!isDarkMode);
    }
```

Após isso, vamos para nosso return. Nele temos o View que irá receber a estilização padrão e `isDarkMode`, vamos adicionar uma imagem a tela, e também um botão `TouchableOpacity` qur irá controlar a mudança de estilos. Feito isso, criamos uma nova Vie, nela temos um `TextInput` com valor `taskName` e que muda com base no `setTaskName. Teremos um botão que ao pressionar acionará o `handleTaskAdd` e nele, irá utilizar uma imagem que servirá como botão. Essa lógica fará com que o essa aplicação adicione novas tarefas dentro da FlatList:

```
return(
    <View style={[styles.container,isDarkMode ? styles.containerDark:styles.container]}>
        <Image
        style={styles.logo}
        source={require('../../components/icons/logo.png')}
        /> 
        <TouchableOpacity onPress={toggleDarkMode} style={styles.buttonDarkMode}>
          <Text>{isDarkMode ? "Modo Claro" : "Modo Escuro"}</Text>
        </TouchableOpacity>


        <View style={styles.form}>

          <TextInput 
            style={styles.input}
            placeholder = "Insira a tarefa aqui"
            placeholderTextColor= "#6B6B6B"
            onChangeText={setTaskName}
            value ={taskName}
          />
          
          <TouchableOpacity  
            onPress={handleTaskAdd}>
              <Image
                style={styles.buttonTask}
                source={require('../../components/icons/send.png')}
              />
          </TouchableOpacity>
```

Juntando todo o nosso código, ele seria assim:

```
import React, {useState} from "react";

import { View , Text, TextInput, TouchableOpacity, FlatList, Alert, Image} from 'react-native';

import { styles } from "./style";

import { Tarefas} from "../../components/Tarefas"



export function Home() {
  const [taskName , setTaskName] = useState('');
  const [tasks , setTask] = useState <String[]> ([]);
  const [isDarkMode, setIsDarkMode] = useState(false);



    function handleTaskAdd() {
      
      const taskLowerCase = tasks.map(task => task.toLowerCase())
      if (taskLowerCase.includes(taskName.toLowerCase())) {
        return Alert.alert("Tarefa existe", "Essa tarefa já existe na lista");
      }
      
      if (taskName.length === 0) {
        return Alert.alert("Espaço vazio", "Nenhuma tarefa foi digitada");

      }
      setTask( previewState => [...previewState ,taskName]);
      setTaskName ('');

    }
    

    function handleTaskRemove(name: string) {
      Alert.alert("Remover",`Remover tarefa: ${name}?`,
      [
        {
          text: "SIM",
          onPress: () => setTask(previewState => previewState.filter(task => task !== name))
        },
        {
          text:"NÃO",
          style: "cancel"
        }
      ])
    }

    function toggleDarkMode() {
      setIsDarkMode(!isDarkMode);
    }
  return(
    <View style={[styles.container,isDarkMode ? styles.containerDark:styles.container]}>
        <Image
        style={styles.logo}
        source={require('../../components/icons/logo.png')}
        /> 
        <TouchableOpacity onPress={toggleDarkMode} style={styles.buttonDarkMode}>
          <Text>{isDarkMode ? "Modo Claro" : "Modo Escuro"}</Text>
        </TouchableOpacity>


        <View style={styles.form}>

          <TextInput 
            style={styles.input}
            placeholder = "Insira a tarefa aqui"
            placeholderTextColor= "#6B6B6B"
            onChangeText={setTaskName}
            value ={taskName}
          />
          
          <TouchableOpacity  
            onPress={handleTaskAdd}>
              <Image
                style={styles.buttonTask}
                source={require('../../components/icons/send.png')}
              />
          </TouchableOpacity>
    
        </View>
        
        <FlatList showsVerticalScrollIndicator ={false}
         
          data={tasks}
          keyExtractor={item => String(item)}
          renderItem={({ item }) => (
            <Tarefas
                key={String (item)}
                name = {String(item)} 
                onRemove ={()=> handleTaskRemove(`${item}`)}/>
          )}
        ListEmptyComponent={() => (
            <Image
              style={styles.noTasks}
              source={require('../../components/icons/list.png')}
            />
        )}  
        />
    </View>
  );
}
```

Temos também, o componente Tarefas, que foi importado no Home. Ele tem como lógica configurar o que foi escrito nas tarefas, e inserir uma checkBox, para que possamos marcar como concluída a nossa tarefa:

```
import { Text,View, TouchableOpacity,Image} from "react-native";
import { styles } from "./style";
import React from 'react'
import BouncyCheckbox from "react-native-bouncy-checkbox";


type Props = {
	name: string;
  onRemove: () => void;
}

export function Tarefas({name, onRemove}: Props){
    return(
        <View style = {styles.container}>
            <Text style ={styles.name}>
            <BouncyCheckbox
                size={25}
                fillColor="green"
                unfillColor="#FFFFFF"
                onPress={(_isChecked: boolean) => {}}            
            />
            {name}
            </Text>

            <TouchableOpacity 
              onPress ={onRemove}>
              <Image
                style={styles.buttonTrash}
                source={require('../../components/icons/trash.png')}
              />
          </TouchableOpacity>
        </View>
    )
}
```

O resultado será a seguinte TodoList:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5la6eiy4lac6mqc187vu.jpeg)

Espero que este artigo tenha ajudado você a criar uma TodoList e entender seu funcionamento. É possível ver esse projeto no meu gitHub pelo link a seguir: https://github.com/altencirsilvajr/Desafio