DEV Community

Cover image for My first project with React ts + Hooks
Beatriz Oliveira
Beatriz Oliveira

Posted on • Updated on

My first project with React ts + Hooks

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.

npx create-react-app TodoList --template typescript

# or

yarn create react-app TodoList --template typescript
Enter fullscreen mode Exit fullscreen mode

2-Step:

With the project created, install Material ui.

# using npm
npm install @material-ui/core

# using yarn
yarn add @material-ui/core
Enter fullscreen mode Exit fullscreen mode

Also add the icon pack:

# using npm
npm install @material-ui/icons

# using yarn
yarn add @material-ui/icons
Enter fullscreen mode Exit fullscreen mode

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

4-Step:

In TodoList.tsx import the hook useState, TextField, ButtonIcons, AddIcon and DeleteIcon from the ui material.

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';
Enter fullscreen mode Exit fullscreen mode

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.

interface TodoItem {
    id: number
    value: string
}
Enter fullscreen mode Exit fullscreen mode

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 :


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)])
    }

Enter fullscreen mode Exit fullscreen mode

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.


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>

Enter fullscreen mode Exit fullscreen mode

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:

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>
      )
    }
Enter fullscreen mode Exit fullscreen mode

the project link :

Oldest comments (2)

Collapse
 
buriti97 profile image
buridev

Very well !!

Collapse
 
franklinuopeople profile image
Franklin Siqueira

Thanks for sharing, Beatriz!