Learn how to find your target audience and match your business goals with their needs: Get the Target Audience Persona Template

How To Build a CRUD App with React and RESTful APIs

by Deborah Iroegbu

August 7, 2023

Share:

Introduction

In this tutorial, we’ll walk through how to build a simple CRUD (Create, Read, Update, Delete) application using React for the frontend and RESTful APIs for the backend. 

By the end of this guide, you will have a solid understanding of how to create a basic web application that can perform CRUD operations on data through HTTP requests.

 

Prerequisites

Before we start, make sure you have the following installed on your laptop or computer:

 

  • Node.js and npm (Node Package Manager) – You can download and install them from the official website: https://nodejs.org/

 

  • A code editor (e.g., Visual Studio Code, Sublime Text, Atom, etc.).

 

Backend Setup: Setting Up RESTful APIs

In case you are wondering what RESTful APIs are, they are programming interfaces that conform to representational state transfer (REST).

To begin, we will create a simple backend using Node.js and Express to provide RESTful APIs for our frontend application. Follow the steps below to set up the backend:

 

Step 1: Project Initialization

Create a new folder for your project and open a terminal in that directory. Run the following command to initialize a new Node.js project:

npm init -y

 

This will generate a package.  json file in your project folder.

 

Step 2: Installing Dependencies

Next, we need to install the required dependencies. For this project, we’ll use Express as our backend framework and Cors to handle cross-origin requests. Run the following command in the terminal:

 

npm install express cors

 

Step 3: Setting Up the Server

Create a new file named server.js in your project folder. This file will contain the server code.

 

// server.js

const express = require('express');

const cors = require('cors');

const app = express();

const port = 5000;

 

app.use(cors());

app.use(express.json());

 

// Your API routes will be defined here

 

app.listen(port, () => {

  console.log(`Server is running on http://localhost:${port}`);

});

 

Also, check out:

How to Build a Full-Stack Web Application with Python and Vue.js

Step 4: Defining API Routes

Now, let’s define the API routes for our CRUD operations. For easy understanding, we’ll use an in-memory array to store our data temporarily. In a real-world scenario, you would use a database.

 

// server.js (continued)

let data = [

  { id: 1, title: 'Task 1', description: 'This is Task 1' },

  { id: 2, title: 'Task 2', description: 'This is Task 2' },

];

 

// GET all tasks

app.get('/api/tasks', (req, res) => {

  res.json(data);

});

 

// GET a single task

app.get('/api/tasks/:id', (req, res) => {

  const id = parseInt(req.params.id);

  const task = data.find((item) => item.id === id);

  if (task) {

    res.json(task);

  } else {

    res.status(404).json({ message: 'Task not found' });

  }

});

 

// POST a new task

app.post('/api/tasks', (req, res) => {

  const { title, description } = req.body;

  const newTask = { id: data.length + 1, title, description };

  data.push(newTask);

  res.status(201).json(newTask);

});

 

// PUT (update) an existing task

app.put('/api/tasks/:id', (req, res) => {

  const id = parseInt(req.params.id);

  const { title, description } = req.body;

  const task = data.find((item) => item.id === id);

  if (task) {

    task.title = title || task.title;

    task.description = description || task.description;

    res.json(task);

  } else {

    res.status(404).json({ message: 'Task not found' });

  }

});

 

// DELETE a task

app.delete('/api/tasks/:id', (req, res) => {

  const id = parseInt(req.params.id);

  data = data.filter((item) => item.id !== id);

  res.sendStatus(204);

});

 

Step 5: Running the Server

To start the server, run the following command in the terminal:

 

node server.js

 

Your backend server is now up and running at http://localhost:5000

 

Frontend Setup: Creating the React App

Now that the backend is set up, let’s create the frontend using React to interact with our RESTful APIs.

 

Step 1: Creating the React App

Open a new terminal window and run the following command to create a new React app:

npx create-react-app crud-app

 

This will create a new directory called crud-app containing the basic structure of a React application.

 

Step 2: Installing Axios

We’ll use Axios to make HTTP requests to our backend. Axios is a popular JavaScript library for handling HTTP requests. Install it by running the following command:

cd crud-app

npm install axios

 

Step 3: Implementing CRUD Operations

Next, let’s build the components to perform CRUD operations.

 

Creating the TaskList Component

Create a new file named TaskList.js in the src folder. This component will display the list of tasks.

 

// TaskList.js

import React, { useState, useEffect } from 'react';

import axios from 'axios';

 

const TaskList = () => {

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

 

  useEffect(() => {

    axios.get('http://localhost:5000/api/tasks')

      .then((response) => setTasks(response.data))

      .catch((error) => console.error(error));

  }, []);

 

  return (

    <div>

      <h2>Task List</h2>

      <ul>

        {tasks.map((task) => (

          <li key={task.id}>

            <strong>{task.title}</strong>

            <p>{task.description}</p>

          </li>

        ))}

      </ul>

    </div>

  );

};

 

export default TaskList;

 

Creating the TaskForm Component

Create a new file named TaskForm.js in the src folder. This component will allow users to add new tasks.

 

// TaskForm.js

import React, { useState } from 'react';

import axios from 'axios';

 

const TaskForm = () => {

  const [title, setTitle] = useState('');

  const [description, setDescription] = useState('');

 

  const handleSubmit = (e) => {

    e.preventDefault();

    const newTask = { title, description };

    axios.post('http://localhost:5000/api/tasks', newTask)

      .then((response) => {

        console.log(response.data);

        // Add the new task to the list

      })

      .catch((error) => console.error(error));

  };

 

  return (

    <div>

      <h2>Add New Task</h2>

      <form onSubmit={handleSubmit}>

        <div>

          <label>Title:</label>

          <input type="text" value={title} onChange={(e) => setTitle(e.target.value)} />

        </div>

        <div>

          <label>Description:</label>

          <textarea value={description} onChange={(e) => setDescription(e.target.value)} />

        </

 

        <div>

          <button type="submit">Add Task</button>

        </div>

      </form>

    </div>

  );

};

 

export default TaskForm;

 

Creating the TaskDetail Component

Create a new file named TaskDetail.js in the src folder. This component will display the details of a single task.

 

// TaskDetail.js

import React, { useState, useEffect } from 'react';

import axios from 'axios';

 

const TaskDetail = ({ taskId }) => {

  const [task, setTask] = useState(null);

 

  useEffect(() => {

    axios.get(`http://localhost:5000/api/tasks/${taskId}`)

      .then((response) => setTask(response.data))

      .catch((error) => console.error(error));

  }, [taskId]);

 

  if (!task) {

    return <div> Loading...</div>;

  }

 

  return (

    <div>

      <h2>{task.title}</h2>

      <p>{task.description}</p>

    </div>

  );

};

 

export default TaskDetail;

 

Step 4: Setting Up App.js

Now that we have our components, we need to use them in the main App.js file.

 

// App.js

import React from 'react';

import TaskList from './TaskList';

import TaskForm from './TaskForm';

import TaskDetail from './TaskDetail';

 

const App = () => {

  return (

    <div>

      <TaskList />

      <TaskForm />

      <TaskDetail taskId={1} /> {/* You can change the taskId to display different task details */}

    </div>

  );

};

 

export default App;

 

Step 5: Running the Frontend

Finally, let’s run the frontend app. Open a terminal in the crud-app directory and run:

 

npm start

 

Your React app will be running at http://localhost:3000.

 

Connecting the Frontend to the Backend

To connect the frontend React app to the backend, we’ll use Axios to make HTTP requests to the RESTful APIs we defined on the backend server.

 

Step 1: Import Axios in the TaskList Component

In the TaskList.js component, we’ll use Axios to fetch the list of tasks from the backend server.

 

// TaskList.js

import React, { useState, useEffect } from 'react';

import axios from 'axios';

 

const TaskList = () => {

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

 

  useEffect(() => {

    axios.get('http://localhost:5000/api/tasks')

      .then((response) => setTasks(response.data))

      .catch((error) => console.error(error));

  }, []);

 

  return (

    <div>

      <h2>Task List</h2>

      <ul>

        {tasks.map((task) => (

          <li key={task.id}>

            <strong>{task.title}</strong>

            <p>{task.description}</p>

          </li>

        ))}

      </ul>

    </div>

  );

};

 

export default TaskList;

 

Step 2: Use Axios in the TaskForm Component

In the TaskForm.js component, we’ll use Axios to send a POST request to add a new task to the backend.

 

// TaskForm.js

import React, { useState } from 'react';

import axios from 'axios';

 

const TaskForm = () => {

  const [title, setTitle] = useState('');

  const [description, setDescription] = useState('');

 

  const handleSubmit = (e) => {

    e.preventDefault();

    const newTask = { title, description };

    axios.post('http://localhost:5000/api/tasks', newTask)

      .then((response) => {

        console.log(response.data);

        // Update the task list with the new task

      })

      .catch((error) => console.error(error));

  };

 

  return (

    <div>

      <h2>Add New Task</h2>

      <form onSubmit={handleSubmit}>

        {/* ... Form fields ... */}

      </form>

    </div>

  );

};

 

export default TaskForm;

 

Step 3: Use Axios in the TaskDetail Component

In the TaskDetail.js component, we’ll use Axios to fetch the details of a single task from the backend.

 

// TaskDetail.js

import React, { useState, useEffect } from 'react';

import axios from 'axios';

 

const TaskDetail = ({ taskId }) => {

  const [task, setTask] = useState(null);

 

  useEffect(() => {

    axios.get(`http://localhost:5000/api/tasks/${taskId}`)

      .then((response) => setTask(response.data))

      .catch((error) => console.error(error));

  }, [taskId]);

 

  if (!task) {

    return <div>Loading...</div>;

  }

 

  return (

    <div>

      <h2>{task.title}</h2>

      <p>{task.description}</p>

    </div>

  );

};

 

export default TaskDetail;

 

With these modifications, the frontend components will communicate with the backend server using Axios to fetch data from the server and send data to create new tasks.

 

Testing the CRUD Operations

Now that both the frontend and backend are up and running, you can test the CRUD operations:

 

Create: Use the TaskForm component to add new tasks. Fill in the title and description, then click the “Add Task” button.

 

Read: The TaskList component will automatically fetch and display all tasks from the backend.

 

Update: To update a task, you can modify the task’s title and description in the TaskForm component and click the “Add Task” button. It will update the task with the same ID.

 

Delete: To delete a task, you can use the DELETE HTTP request in the backend. However, in this tutorial, we didn’t implement a delete feature. You can extend the backend API by adding a DELETE route to handle task deletion.

 

Conclusion

Congratulations! You have successfully built a basic CRUD app using React and RESTful APIs. 

This tutorial explains how to set up a simple backend with Node.js and Express and how to create React components to interact with the backend through Axios for performing CRUD operations.

Remember, this is just a starting point, and there are many ways to improve and expand upon this application. Some possible enhancements include adding form validation, implementing user authentication, and connecting to a real database for an organized data storage.

 

Happy coding!

 





Author

Deborah Iroegbu

Deborah Iroegbu

Related Articles