how I built a Task Tracker Application with React and Json Server
Tags: restapi, crudoperation, frontend, react
Published: 2023-03-14 12:53:09

## Explanation of task tracker app:

A task tracker app is a software application that helps users organize and manage their tasks. It allows users to create tasks, set priorities, and track progress. A task tracker app can be useful for individuals or teams who need to stay on top of their workloads and ensure that tasks are completed on time.

##  Overview of React and JSON Server:

React is a popular JavaScript library for building user interfaces. It allows developers to create reusable UI components and build complex web applications using a declarative syntax. React is widely used for building single-page applications (SPAs) and has a large and active community of developers.

JSON Server is a tool that allows developers to create a fake REST API using a JSON file. It can be used to simulate a server-side API for testing and prototyping purposes. JSON Server is easy to set up and use, and it can be a great tool for building a task tracker app quickly.

## Purpose of this article:

The purpose of this article is to provide a step-by-step guide on how to build a task tracker app using React and JSON Server. By the end of this article, readers should be able to create a basic task tracker app that allows them to add, delete, and edit tasks, and stores the task data in a JSON file. This article is intended for intermediate-level developers who are familiar with JavaScript and React, but who may not have experience with JSON Server.


## Installing Node.js and React:

Before getting started, you need to make sure you have Node.js and React installed on your computer. To install Node.js, go to the official Node.js website and download the latest stable version for your operating system. Once you've installed Node.js, you can use npm (Node Package Manager) to install React. Open your terminal or command prompt and type the following command:

```
npx create-react-app a-task-tracker-app

```

The above command will create a new directory called my-task-tracker-app and set up a new React project inside it. It will also install all the necessary dependencies.

## Installing JSON Server:

To install JSON Server, open your terminal or command prompt and navigate to your project directory:

```
cd a-task-tracker-app

```
Once you're inside your project directory, type the following command to install JSON Server:

```
npm install -g json-server

```
The above command will install JSON Server globally on your computer. You can now use JSON Server to create a fake REST API for your task tracker app.

## Defining the app's components and UI:

Before starting to write code, it's important to define the app's components and UI. In a task tracker app, the main components are usually a list of tasks, a form for adding new tasks, and a way to edit or delete existing tasks. The UI should be simple and easy to use, with clear visual cues for the user.

## Creating the necessary React components:
Now that you have a clear idea of the app's components and UI, it's time to start building the React components. In your project directory, navigate to the src folder and create a new folder called components. Inside the components folder, create three new files: TaskList.js, TaskForm.js, and Task.js.

TaskList.js should contain the code for displaying a list of tasks. 
AddTask.js should contain the code for the form used to add new tasks. 
Task.js should contain the code for each individual task in the list.

Here's the code snippet for TaskList.js:

```
import Task from "./Task"

const TaskList = ({ tasks,onDelete,onToggle}) => {
  return (
    <>
    {tasks. Map((task, index) => (
      <Task key={index} task={task}
      onDelete={onDelete} OnToggle={onToggle}/>
    ))}    
    </>
  )
}

export default TaskList

```
Here's a code snippet for AddTask.js:

```
/* import {useState} from 'react'

const AddTask = ({onAdd}) => {
const [text,setText] = useState('')
const [day,setDay] = useState('')
const [reminder,setReminder] = useState(false)

const onSubmit = (e) => {
e.preventDefault() //prevent the page from reloading

if(!text) {
    alert('please add a task')
    return
} //validating the input

onAdd({text,day,reminder})

setText('')
setDay('')
setReminder(false)
}
*/

  return (
    <form className="add-form" onSubmit={handleSubmit}>
      <div className="form-control">
        <label>Task</label>
        <input
          type="text"
          placeholder="Add Task"
          value={text}
          onChange={(e) => setText(e.target.value)}
        />
      </div>
      <div className="form-control">
        <label>Day & Time</label>
        <input
          type="text"
          placeholder="Add Day & Time"
          value={day}
          onChange={(e) => setDay(e.target.value)}
        />
      </div>
      <div className="form-control form-control-check">
        <label>Set Reminder</label>
        <input
          type="checkbox"
          checked={reminder}
          value={reminder}
          onChange={(e) => setReminder(e.currentTarget.checked)}
        />
      </div>
      <input type="submit" value="save Task" className="btn btn-block" />
    </form>
  );
}

export default AddTask

```
Here's a code snippet for Task.js:

```
import {FaTimes} from 'react-icons/fa'

const Task = ({task,onDelete,onToggle}) => {
  return (
    <div className={`task ${task. Reminder ? 
    'reminder' : ''}`} //using condition to style the div
    onDoubleClick={() => 
    onToggle(task.id)}>
    <h3>{task. Text} {' '}

    <FaTimes
      style={{color:'red',cursor:'pointer'}}
      onClick={() => onDelete(task.id)}
    />
    </h3>
    <p>{task. Day}</p>
    
    </div>
  )
}

export default Task

```

## Styling the app with CSS:

To style the app, you can create a new file called index.css in your src folder and add CSS styles for your components. Here's a CSS code snippet for the App:

```
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400&display=swap');

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

body {
  font-family: 'Poppins', sans-serif;
}

.container {
  max-width: 500px;
  margin: 30px auto;
  overflow: auto;
  min-height: 300px;
  border: 1px solid steelblue;
  padding: 30px;
  border-radius: 5px;
}

.header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
}

.btn {
  display: inline-block;
  background: #000;
  color: #fff;
  border: none;
  padding: 10px 20px;
  margin: 5px;
  border-radius: 5px;
  cursor: pointer;
  text-decoration: none;
  font-size: 15px;
  font-family: inherit;
}

.btn:focus {
  outline: none;
}

.btn:active {
  transform: scale(0.98);
}

.btn-block {
  display: block;
  width: 100%;
}

.task {
  background: #f4f4f4;
  margin: 5px;
  padding: 10px 20px;
  cursor: pointer;
}

.task. Reminder {
  border-left: 5px solid green;
}

.task h3 {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.add-form {
  margin-bottom: 40px;
}

.form-control {
  margin: 20px 0;
}

.form-control label {
  display: block;
}

.form-control input {
  width: 100%;
  height: 40px;
  margin: 5px;
  padding: 3px 7px;
  font-size: 17px;
}

.form-control-check {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.form-control-check label {
  flex: 1;
}

.form-control-check input {
  flex: 2;
  height: 20px;
}

footer {
  margin-top: 30px;
  text-align: center;
}
```

Make sure to import your CSS file in the App.js file and add the appropriate classes to your components.

## Creating a new JSON file for the task data:

To create a fake REST API for your task tracker app, you need to create a new JSON file that will store the task data. In your project directory, create a new folder called db and inside it, create a new file called db.json.

Here's an example code for db.json:

```
{
  "tasks": [
    {
      "text": "DummyAPI is a RESTful online fake API, publicly accessible via https.
",
      "day": "March 1",
      "reminder": true,
      "id": 2
    },
    {
      "text": "LAST one",
      "day": "Tuesday",
      "reminder": true,
      "id": 3
    },
    {
      "text": "fake dummy",
      "day": "february 20",
      "reminder": true,
      "id": 5
    },
    {
      "text": " jinni",
      "day": "march 1",
      "reminder": true,
      "id": 6
    }
  ]
}
```
## Starting the JSON Server:

To start the JSON Server, open your terminal or command prompt and navigate to your project directory. Then, type the following command:

```
json-server --watch db/db.json --port 5000

```
This command will start the JSON Server and watch for changes in the db.json file. It will also run the server on port 5000.

## Testing the server connection:
To test the server connection, open your browser and go to http://localhost:5000/tasks. If the server is running correctly, you should see the task data displayed in JSON format.

You can also test the CRUD operations by using a tool like Postman to send GET, POST, PUT, and DELETE requests to the server. 

For example, to add a new task, you can send a POST request to `http://localhost:5000/tasks` with the new task data in the request body. The server will respond with the new task data, including a unique ID generated by the server.

## Creating a new task:
To create a new task, we need to implement the create operation. In the AddTask component, we can define a handleSubmit function that sends a POST request to the JSON Server to add a new task.

Here's a  code snippet:

```
export const handleSubmit = async (e) => {
  e.preventDefault();

const AddTasks = async (task) => {
    const response = await fetch('http://localhost:5000/tasks',{
      method:'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(task),
    })
    const data = await response.json()
    setTasks([...tasks, data]);
}
}
```
## Reading all tasks:

To read all the tasks from the server, we need to implement the read operation. In the App component, we can define a useEffect hook that fetches the task data from the server when the component mounts. 

Here's the code snippet:

```
const [tasks, setTasks] = useState([]);

useEffect(() => {
  const getTasks = async () => {
    const tasksFromServer = await fetchTasks();
    setTasks(tasksFromServer);
  };

  getTasks();
}, []);

const fetchTasks = async () => {
  const res = await fetch('http://localhost:5000/tasks');
  const data = await res.json();

  return data;
};

```

## Updating a task:
To update an existing task, we need to implement the update operation. In the Task component, we can define a Toggle function that sends a PUT request to the server to update the reminder status of the task. 

Here's the code snippet:

```
export const onToggle = async (e) => {
  e.preventDefault();
 
const updateTask = async (id, updatedTask) => {
  const res = await fetch(`http://localhost:5000/tasks/${id}`, {
    method: 'PUT',
    headers: {
      'Content-type': 'application/json',
    },
    body: JSON.stringify(updatedTask),
  })

  const data = await res.json()

  setTasks(
    tasks. Map((task) =>
      task.id === id ? { ...task, reminder: data. Reminder } : task
    )
  )
}
}
```
The above code snippet uses the fetch API to send a PUT request to the server with the updated task data in JSON format. After the server responds with the updated task data, the tasks state is updated to reflect the changes.

## Deleting a task:

To delete a task, you will need to send a DELETE request to the JSON Server with the task ID.

Here's the code snippet for deleting a task:

```
const deleteTask = async (id) => {
  await fetch(`http://localhost:5000/tasks/${id}`, { method: 'DELETE' })

  setTasks(tasks. Filter((task) => task.id !== id))
}

```

This code uses the fetch API to send a DELETE request to the server with the task ID. After the server confirms that the task has been deleted, it is removed from the tasks state using the filter method.


## Updating the UI based on server data:

After sending a request to the server and receiving a response, you will need to update the app's UI with the data returned from the server. For example, after creating a new task, you will need to add the new task to the tasks state and update the task list displayed in the UI.

Here's an example code that connects the app to the JSON Server and handles server responses:

```
import { useState, useEffect } from 'react'

const App = () => {
  const [tasks, setTasks] = useState([])

  useEffect(() => {
    const getTasks = async () => {
      const tasksFromServer = await fetchTasks()
      setTasks(tasksFromServer)
    }

    getTasks()
  }, [])

  const fetchTasks = async () => {
    const res = await fetch('http://localhost:5000/tasks')
    const data = await res.json()

    return data
  }

  const addTask = async (task) => {
    const res = await fetch('http://localhost:5000/tasks', {
      method: 'POST',
      headers: {
        'Content-type': 'application/json',
      },
      body: JSON.stringify(task),
    })

    const data = await res.json()

    setTasks([...tasks, data])
  }

  const deleteTask = async (id) => {
    await fetch(`http://localhost:5000/tasks/${id}`, { method: 'DELETE' })

    setTasks(tasks.filter((task) => task.id !== id))
  }

  return (
    <div className='container'>
      <Header />
      <AddTask onAdd={addTask} />
      {tasks.length > 0 ? (
        <Tasks tasks={tasks} onDelete={deleteTask} />
      ) : (
        'No tasks to show'
      )}
    </div>
  )
}

export default App

```
In the above code example, the app uses the useEffect hook to fetch tasks from the server when the app component is mounted. The fetchTasks function sends a GET request to the server to retrieve the task data. The addTask function sends a POST request to the server to add a new task. The deleteTask function sends a DELETE request to the server to delete a task. The app's UI is updated using the setTasks function to add or remove tasks from the tasks state.

## Conclusion

This article provided a step-by-step guide to building a task tracker app with React and JSON Server. This article covered setting up the development environment, designing the app's components and UI, setting up the JSON Server, implementing the CRUD operations, and connecting the app to the JSON Server.


## Here is my final thought

Building a task tracker app with React and JSON Server is a great way to learn and practice web development skills. React provides a powerful toolset for creating dynamic and responsive user interfaces, while JSON Server makes it easy to set up a fake REST API for testing and development purposes.

Here is a link to the Repository on Github for reference 
[Project](https://github.com/Noibisjunior/Task-Tracker-Application)

Here is also a link to the live Demo [live version](https://task-tracker-application-ruby.vercel.app/)

Kindly Follow Me on  [Twitter](https://twitter.com/Clericcoder)