My first project with React ts + Hooks
Tags: react, typescript, hooks, materialui
Published: 2021-04-04 19:35:50

Well, the project that will be presented is very simple, but served to consolidate basic knowledge about React, I chose to use typescript, because the code becomes more readable and simple, but if you prefer you can use normal javascript.

The project will use:
* Typescript
* React Hooks
* Material UI

## 1-Step:
Create the project with create-react-app TodoList using or not the Typescript template.
```sh
npx create-react-app TodoList --template typescript

# or

yarn create react-app TodoList --template typescript
```
## 2-Step:
With the project created, install Material ui.
```sh
# using npm
npm install @material-ui/core

# using yarn
yarn add @material-ui/core
```
Also add the icon pack:
```sh
# using npm
npm install @material-ui/icons

# using yarn
yarn add @material-ui/icons
```
## 3-Step:
Create a file ``TodoList.tsx`` where all the project code will be, also create a styles folder containing ``TodoList.css`` if you want to style the project.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sihd8xz1brd9h8dsnfkm.png)
## 4-Step:
In ``TodoList.tsx`` import the hook useState, TextField, ButtonIcons, AddIcon and DeleteIcon from the ui material.
```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';
```
Next we will create an ``interface``, interface in typescript is the way to name types, so we will create our TodoItem interface passing the value of id as number and value as a string.
```ts
interface TodoItem {
    id: number
    value: string
}
```
Create a state useState ``set`` and ``setList`` with an array of type ``TodoItem`` , in its default value we will pass an array with ``id: 0``, and the empty string ``value: ''``. Then we'll create functions of type ``handleChange``, ``handleAdd`` and ``handleDelete`` to handle this 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-Step:
In the ``return`` pass a ``list.map`` taking the ``item`` and the ``index``, rendering a ``div``,where we will pass a ``key`` with value ``item.id`` which will be unique to each item, then we will also render the ``TextField`` from the ui material with a ``value`` and the ``onChange``. Then we pass the ``IconButton`` also from the material ui rendering the ``IconAdd`` with an ``onClick`` and we do the same thing with the ``IconDelete`` but passing the ``handleDelete`` instead of the ``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>

```
Note.1: the ``list.length`` is the quantity of the list,in other words, it will always start with 1 item.
Note.2: We will also create a variable ``let count = 1`` to simulate an id.

## Result
The ``TodoList.tsx`` will look like this:
```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>
      )
    }
```
the project link :
- https://github.com/biantris/todolist
- https://todolist-git-master-beatrizoliveira250.vercel.app/
- Version pt-BR:
https://dev.to/beatrizoliveira250/meu-primeiro-projeto-com-react-ts-444