Crud-react-app with json-server and axios
Tags: react, crud, axios, tailwindcss
Published: 2023-08-12 14:02:29

Hi, here we want to make a simple crud app with `react hooks` by using `json-server`, `axios` and `Tailwind CSS` for styling.
In this app we have two fields: **name**, **username** with three default values that we can edit, delete them or add a new one.
You can find source code here: [source code](https://github.com/NeginSal/React-Hook-CRUD)

![project home page](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ygr2b3y2fyvrvqq7gx7j.png)
let's start this project together step by step:

---

**1. Setup project**

Run `npx create-react-app react-crud-app` to create a new app. Open the project and run `npm start` to see the project in your browser and then open a new terminal and run this command to start json-server :`npx json-server --watch data/data.json --port 8000`  

---

**2. Files & Folder**
we just need App.js file and delete other files. Then create two folders: `components` & `data`.

###### **Components** :
In the `src` folder, create a `components` folder to put all of our files inside it. We have four components inside this folder :

`AddUser.js`: to add a user

`EditUser.js`: to edit a user

`UserList.js`: to show all users

`Home.js`: it is our homepage

###### **data**: 
It is in the root folder. Inside this folder create a file and called it `data.json` and put all of our data inside it.

```
{
  "users":[
    {
      "name":"Negin",
      "username":"negin007",
      "id":1
    },
    {
      "name":"Craig",
      "username":"benisphere",
      "id":2
    },
    {
      "name":"Ben",
      "username":"siliconeidolon",
      "id":3
    }
  ]
}
```

---

**3. Code**
#####**App.js**:  

add path for components by using `react-router-dom`:


```
import React from 'react';
import { Routes, Route } from "react-router-dom";
import Home from './components/Home';
import EditUser from './components/EditUser';
import AddUser from './components/AddUser';

const App = () => {
  return (
    <>
      <Routes>
        <Route path='/' element={<Home />} />
        <Route path='/edit/:id' element={<EditUser />} />
        <Route path='/create' element={< AddUser />} />
      </Routes>
    </>
  );
}

export default App;
```


#####**Home.js**:  

This is your home component, where you can see a list of users (`UserList.js`) and add a new user(`AddUser`).
Also, here we have a `useEffect` to fetch all users and a function(`deleteUser`) for deleting a user.

```
import axios from "axios";
import { useEffect, useState } from "react";
import UserList from "./UserList";
import AddUser from "./AddUser";

const Home = () => {
  const [users, setUsers] = useState([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    setLoading(true)
    axios.get("http://localhost:8000/users")
      .then(response => {
        setUsers(response.data)
      })
    setLoading(false)
  }, [])

  const deleteUser = (id) => {
    axios.delete(`http://localhost:8000/users/${id}`).then((response) => {
      const newUser = users.filter((user) => user.id !== id);
      console.log(response)
      setUsers(newUser);
    }).catch(error => {
      console.log(error)
    });
  }

  return (
    <div className="max-w-xl pb-8 mx-auto px-5 bg-slate-100">
      <UserList
        users={users}
        loading={loading}
        deleteUser={deleteUser}
      />
      <AddUser
        users={users}
        setUsers={setUsers}
      />
    </div>
  );
}

export default Home;
```

#####**UserList.js**:  

A component for showing list of users.

Here we're passing `users`, `loading`, `deleteUser` as props to this component: `users`: list of users, `loading`: for the time before user loaded on the page and `deleteUser` function for deleting a user.

Another important thing in this component is edit button:
we wrap it inside a `Link` component and then when user click on this button it navigates to `EditUser` component.

```
import { Link } from "react-router-dom";

const UserList = ({ users, loading, deleteUser }) => {
  
  return (
    <div className='py-5'>
      {loading && <p>loading ...</p>}
      {users &&
        <ul>
          {(users.map((user) =>
            <li className='flex justify-between border-b-4' key={user.id}>
              <div className="flex ">
                <p className='my-3 px-3'>{user.name}</p>
                <p className='my-3 px-3'>{user.username}</p>
              </div>
              <div>
                <Link to={`/edit/${user.id}`}>
                  <button
                    className='mx-2 my-3 px-2 py-1 text-green-800
                       hover:bg-green-400 hover:rounded-md hover:border hover:border-green-800'
                  >EDIT</button>
                </Link>
                <button
                  className='my-3 px-2 py-1 text-red-800 
                        hover:bg-red-400 hover:rounded-md hover:border hover:border-red-800'
                  onClick={() => deleteUser(user.id)}
                >Delete</button>
              </div>
            </li>
          ))}
        </ul >
      }
    </div >
  )
}

export default UserList;
```

#####**AddUser.js**: 

It is a form with two input fields (name & username)  and a button to submit a new user. Here we pass `setUsers`, `users`  as props to this component.

For submitting a new user we have `handleSubmit` function and inside this function we make a post request to post new name and username and the pass it to `setUsers` and then make the fields empty.

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

const AddUser = ({ setUsers, users }) => {
	const [name, setName] = useState("")
	const [username, setUserName] = useState("")

	const handleSubmit = (e) => {
		e.preventDefault();
		axios
			.post(`http://localhost:8000/users`, { name, username })
			.then((res) => {
				setUsers([...users, res.data])
				setName('');
				setUserName('');
			});
	};

	return (
			<form onSubmit={handleSubmit}>
				<div className='flex flex-col justify-center items-center sm:flex-row sm:justify-evenly'>
					<div className='mb-2'>
						<input
							className='px-3 py-1 rounded-full border border-gray-600'
							value={name} onChange={(e) => setName(e.target.value)} required
							type="text" placeholder="Name" />
					</div>
					<div className='mb-2'>
						<input
							className='px-3 py-1 rounded-full border border-gray-600'
							value={username} onChange={(e) => setUserName(e.target.value)} required
							type="text" placeholder="UserName" />
					</div>
					<div className='mb-2'>
						<button className="bg-blue-500 hover:bg-blue-700 text-white py-1 px-3 rounded-full">
							Add
						</button>
					</div>
				</div>
			</form>
	);
}

export default AddUser;
```

#####**EditUser.js**: 

This component is for editing each user, after click on edit button then we navigate to this component. Here we have a `useEffect` for loading the data that we want to edit and then a `handleSubmit` function for submitting the edited item.

```
import axios from "axios";
import { useEffect, useState } from "react";
import { useNavigate, useParams } from "react-router";

const EditUser = () => {
  const [data, setData] = useState([])
  const [name, setName] = useState('');
  const [username, setUserName] = useState('');

  const { id } = useParams();
  const navigate = useNavigate()

  useEffect(() => {
    axios.get("http://localhost:8000/users/" + id)
      .then(response => {
        const data = response.data;
        setName(data.name);
        setUserName(data.username);
      })
      .catch(error => console.log(error))
  }, [id])

  const handleSubmit = (e) => {
    e.preventDefault()
    axios.put("http://localhost:8000/users/" + id, {
      name,
      username
    })
      .then(response => {
        setData(response.data);
        navigate('/')
      })
  }

  const goHome = () => {
    navigate('/')
  }

  return (
    <div className="flex items-center justify-center">
      <form onSubmit={handleSubmit}>
        <div className='flex flex-col justify-center items-center bg-slate-100 p-10 mt-10 rounded-md'>
          <input
            className='my-2 px-5 py-1 rounded-full border border-gray-600'
            type="text" placeholder="Name"
            value={name}
            onChange={(e) => setName(e.target.value)}
          />
          <input
            className='my-2 px-5 py-1 rounded-full border border-gray-600'
            type="text" placeholder="UserName"
            value={username}
            onChange={(e) => setUserName(e.target.value)}
          />
          <div className="flex my-2">
            <button
              className='text-white mx-1 px-5 py-1 rounded-full bg-blue-500 hover:bg-blue-700'>
              EDIT
            </button>
            <button
              onClick={goHome}
              className='text-white mx-1 px-5 py-1 rounded-full bg-blue-500 hover:bg-blue-700'
            >
              CANCEL
            </button>
          </div>
        </div>
      </form>
    </div>

  );
}

export default EditUser;
```

---
Now here we go! We created a simple `crud app` with `react-hook`, `json-server`, `Axios` and `Tailwind CSS`. In the below I put links that are helpful for me to create this project:

[Build a CRUD App in React with Hooks](https://www.taniarascia.com/crud-app-in-react-with-hooks/)

Thank you for reading! :four_leaf_clover: