Meu primeiro projeto com React ts + Hooks
Tags: react, typescript, hooks, materialui
Published: 2021-03-02 17:31:26

Bom, o projeto que será apresentado é bem simples, mas serviu para consolidar conhecimentos básicos sobre React, optei por utilizar o typescript, pois o código se torna mais legível e simples, mas se preferir pode utilizar javascript normal. 

No projeto será utilizado:
* Typescript
* React Hooks
* Material UI

## 1) Passo:
Criar o projeto com create-react-app TodoList usando ou não o template de Typescript.
```sh
npx create-react-app TodoList --template typescript

# or

yarn create react-app TodoList --template typescript
```
## 2) Passo:
Já com o projeto criado instale o Material ui.
```sh
# utilizando o npm
npm install @material-ui/core

# utilizando o yarn
yarn add @material-ui/core
```
Também adicione o pacote de ícones:
```sh
# usando npm
npm install @material-ui/icons

# usando yarn
yarn add @material-ui/icons
```
## 3) Passo:
Crie um o arquivo ``TodoList.tsx`` onde ficará todo o código do projeto, crie também uma pasta styles contendo ``TodoList.css`` se você quiser estilizar o projeto.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sihd8xz1brd9h8dsnfkm.png)

## 4) Passo:
Em ``TodoList.tsx`` importe o hook useState, TextField, ButtonIcons, AddIcon e DeleteIcon do material ui.
```ts
import React, { useState } from 'react';
import { TextField, IconButton } from '@material-ui/core';
import AddIcon from '@material-ui/icons/Add';
import DeleteIcon from '@material-ui/icons/Delete';
```
Em seguida vamos criar uma ``interface`` , interface no typescript é a forma de nomear os tipos, com isso criaremos nossa interface TodoItem passando o valor do id como number e value como uma string.
```ts
interface TodoItem {
    id: number
    value: string
}
```
Crie um state useState ``set`` e ``setList`` com um array do tipo ``TodoItem`` , no seu valor default vamos passar um array com ``id: 0``, e o uma string vazia ``value: ''``. Depois iremos criar funções do tipo ``handleChange``, ``handleAdd`` e ``handleDelete`` para lidar com esse list :
```ts

export const TodoList: React.FC = () => {
    const [list, setList] = useState<TodoItem[]>([{ id: 0, value: '' }])

    const handleChange = (value: string, id: TodoItem['id']) => {
        setList(prev => prev.map(item => item.id === id ? { ...item, value } : item ))
    }

    const handleDelete = (id: TodoItem['id']) => {
        setList(prev => prev.filter(item => item.id !== id))
    }

    const handleAdd = (index: number) => {
        const newItem = { id: count ++, value: '' }
        setList(prev => [...prev.slice(0, index + 1), newItem, ...prev.slice(index + 1)])
    }

```
## 5) Passo:
No ``return`` passe uma ``list.map`` pegando o ``item `` e o ``index``, renderizando uma ``div``,onde iremos passar uma ``key`` com valor ``item.id`` que será único para cada item, em seguida vamos renderizar também o ``TextField`` do material ui com um ``value`` e o ``onChange``. Depois passamos o ``IconButton`` também do material ui rederizando o ``IconAdd`` com um ``onClick`` e faremos a mesma coisa com o ``IconDelete``, porém passando o ``handleDelete`` ao invés do ``handleAdd``.
```ts

return (
        <div>
          {list.map((item, index) => (
            <div key={item.id}>
              <TextField
                value={item.value}
                onChange={e => handleChange(e.currentTarget.value, item.id)}
              />
              <IconButton onClick={() => handleAdd(index)}>
                <AddIcon />
              </IconButton>
              
              {list.length > 1 && (
                <IconButton onClick={() => handleDelete(item.id)}>
                  <DeleteIcon />
                </IconButton>
              )}
            </div>
          ))}
        </div>

```
Obs.1: a ``list.length`` é a quantidade da lista, ou seja, ela sempre vai começar com 1 item.
Obs.2: Também criaremos uma váriavel ``let count = 1`` para simular um id.

## Resultado
O ``TodoList.tsx`` ficará assim:
```ts
import React, { useState } from 'react';
import { TextField, IconButton } from '@material-ui/core';
import AddIcon from '@material-ui/icons/Add';
import DeleteIcon from '@material-ui/icons/Delete';

interface TodoItem {
    id: number
    value: string
}

let count = 1

export const TodoList: React.FC = () => {
    const [list, setList] = useState<TodoItem[]>([{ id: 0, value: '' }])

    const handleChange = (value: string, id: TodoItem['id']) => {
        setList(prev => prev.map(item => item.id === id ? { ...item, value } : item ))
    }

    const handleDelete = (id: TodoItem['id']) => {
        setList(prev => prev.filter(item => item.id !== id))
    }

    const handleAdd = (index: number) => {
        const newItem = { id: count ++, value: '' }
        setList(prev => [...prev.slice(0, index + 1), newItem, ...prev.slice(index + 1)])
    }

    return (
        <div>
          {list.map((item, index) => (
            <div key={item.id}>
              <TextField
                value={item.value}
                onChange={e => handleChange(e.currentTarget.value, item.id)}
              />
              <IconButton onClick={() => handleAdd(index)}>
                <AddIcon />
              </IconButton>
              
              {list.length > 1 && (
                <IconButton onClick={() => handleDelete(item.id)}>
                  <DeleteIcon />
                </IconButton>
              )}
            </div>
          ))}
        </div>
      )
    }
```
o link do projeto :
- https://github.com/beatrizoliveiira/todolist
- https://todolist-git-master-beatrizoliveira250.vercel.app/
- Versão em inglês:
https://dev.to/beatrizoliveira250/my-first-project-with-react-ts-hooks-3mji