Full-Stack App with React and Node

In today’s digital landscape, knowing how to build a full-stack application is a crucial skill for any aspiring web developer. Whether you’re new to development or expanding your JavaScript skills, React JS and Node.js are excellent tools for crafting dynamic, modern web applications. This guide will walk you through the steps of building your first full-stack application using React for the front end and Node.js for the back end.

Let’s dive in!

Why Choose React and Node.js?

React is a popular JavaScript library for building user interfaces, particularly single-page applications (SPAs). Its component-based architecture makes it perfect for creating dynamic, reusable UI components.

On the other hand, Node.js allows you to build server-side applications using JavaScript. With the power of Express.js, a minimal and flexible Node.js framework, you can create a REST API that communicates seamlessly with your React frontend.

Together, React and Node.js make a powerful duo for full-stack web development.

Planning Your Application

Before jumping into code, let’s plan the features of the full-stack application we’ll build. For this tutorial, we’ll create a simple task manager where users can:

  1. Create new tasks
  2. View a list of tasks
  3. Mark tasks as complete
  4. Delete tasks

This will allow you to work with core full-stack concepts such as CRUD operations (Create, Read, Update, Delete), REST APIs, and database interactions.

Setting Up the Backend: Node.js and Express

  1. Initialize the Project

First, create a new folder for your backend and initialize it with npm init to generate a package.json file.

mkdir task-manager-backend
cd task-manager-backend
npm init -y
  1. Install Dependencies

Next, install Express.js to handle your server and API routes, and nodemon for automatically restarting the server when files change.

npm install express
npm install -D nodemon

Update the package.json file to use nodemon:

"scripts": {
  "start": "nodemon index.js"
}
  1. Create a Basic Server

Create an index.js file and write a simple server that listens on port 5000.

const express = require('express');
const app = express();

app.use(express.json());

app.get('/', (req, res) => {
  res.send('Welcome to the Task Manager API');
});

app.listen(5000, () => {
  console.log('Server running on port 5000');
});

Run the server with:

npm start

Navigate to http://localhost:5000/ in your browser, and you should see the welcome message from your server.

  1. Define RESTful Routes

Create routes for managing tasks (create, read, update, delete). We’ll use a simple array to store tasks temporarily.

let tasks = [];

app.post('/tasks', (req, res) => {
  const task = { id: tasks.length + 1, text: req.body.text, completed: false };
  tasks.push(task);
  res.status(201).send(task);
});

app.get('/tasks', (req, res) => {
  res.send(tasks);
});

app.patch('/tasks/:id', (req, res) => {
  const task = tasks.find(t => t.id === parseInt(req.params.id));
  if (!task) return res.status(404).send('Task not found.');
  task.completed = req.body.completed;
  res.send(task);
});

app.delete('/tasks/:id', (req, res) => {
  const taskIndex = tasks.findIndex(t => t.id === parseInt(req.params.id));
  if (taskIndex === -1) return res.status(404).send('Task not found.');
  const deletedTask = tasks.splice(taskIndex, 1);
  res.send(deletedTask);
});

With these routes in place, you can now create, retrieve, update, and delete tasks via the API.

Building the Frontend: React

Now that the backend is set up, let’s move to the React frontend.

  1. Create a React App

Navigate back to the root directory and create a new React application using create-react-app.

npx create-react-app task-manager-frontend
cd task-manager-frontend
  1. Install Axios

Axios is a promise-based HTTP client that will help us make API calls from our React app to the Node.js backend.

npm install axios
  1. Creating the UI

Open the src folder, and let’s first create a basic UI for adding and displaying tasks. Start by setting up the state to hold the list of tasks and a simple form for adding new tasks.

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

const App = () => {
  const [tasks, setTasks] = useState([]);
  const [taskText, setTaskText] = useState('');

  useEffect(() => {
    fetchTasks();
  }, []);

  const fetchTasks = async () => {
    const response = await axios.get('http://localhost:5000/tasks');
    setTasks(response.data);
  };

  const addTask = async () => {
    const newTask = { text: taskText };
    const response = await axios.post('http://localhost:5000/tasks', newTask);
    setTasks([...tasks, response.data]);
    setTaskText('');
  };

  return (
    <div>
      <h1>Task Manager</h1>
      <input
        type="text"
        value={taskText}
        onChange={(e) => setTaskText(e.target.value)}
        placeholder="Add a new task"
      />
      <button onClick={addTask}>Add Task</button>

      <ul>
        {tasks.map((task) => (
          <li key={task.id}>
            {task.text} - {task.completed ? 'Completed' : 'Pending'}
          </li>
        ))}
      </ul>
    </div>
  );
};

export default App;

Here’s what’s happening:

  • We’re using useState to store tasks and the new task input.
  • The fetchTasks function fetches tasks from the backend API using Axios.
  • addTask sends a POST request to the API to create a new task.
  1. Mark Tasks as Complete

Next, let’s allow users to mark tasks as complete. In the task list, add a button to toggle the task’s status.

const toggleTaskCompletion = async (id, completed) => {
  await axios.patch(`http://localhost:5000/tasks/${id}`, { completed: !completed });
  fetchTasks();
};

return (
  <ul>
    {tasks.map((task) => (
      <li key={task.id}>
        {task.text} - {task.completed ? 'Completed' : 'Pending'}
        <button onClick={() => toggleTaskCompletion(task.id, task.completed)}>
          {task.completed ? 'Undo' : 'Complete'}
        </button>
      </li>
    ))}
  </ul>
);
  1. Delete Tasks

Finally, add functionality to delete tasks:

const deleteTask = async (id) => {
  await axios.delete(`http://localhost:5000/tasks/${id}`);
  fetchTasks();
};

return (
  <ul>
    {tasks.map((task) => (
      <li key={task.id}>
        {task.text} - {task.completed ? 'Completed' : 'Pending'}
        <button onClick={() => toggleTaskCompletion(task.id, task.completed)}>
          {task.completed ? 'Undo' : 'Complete'}
        </button>
        <button onClick={() => deleteTask(task.id)}>Delete</button>
      </li>
    ))}
  </ul>
);

Conclusion

Congratulations! You’ve built your first full-stack application using React and Node.js. While this task manager is simple, you now have a solid understanding of how the front end and back end communicate through APIs, how to work with React’s state, and how to perform CRUD operations with a Node.js server. You can expand this project by adding a database (like MongoDB), user authentication, or additional features to solidify your skills.

Leave a Reply

Your email address will not be published. Required fields are marked *