DEV Community

Cover image for Building a Full-Stack Web App with Node.js and React: A Step-by-Step Guide
Yevhen Kozachenko 🇺🇦
Yevhen Kozachenko 🇺🇦

Posted on

Building a Full-Stack Web App with Node.js and React: A Step-by-Step Guide

In today’s fast-paced digital world, building scalable, maintainable, and performant web applications is more crucial than ever. Whether you're a beginner web developer or looking to refine your workflow, understanding how to work across the stack can open doors to greater flexibility and efficiency in your projects. In this Medium post, we’ll dive into building a full-stack web application using Node.js for the backend and React for the frontend.

This guide is designed to walk you through the full process—starting from setting up your environment, creating an API with Node.js and Express, connecting it to a MongoDB database, and integrating it with a modern React frontend. By the end of this tutorial, you’ll have a fully functional CRUD (Create, Read, Update, Delete) web application.

Why Choose Node.js and React?

Both Node.js and React are extremely popular choices among web developers today.

  • Node.js allows for writing server-side code using JavaScript, unifying the programming language used on both front and back ends.
  • React is a powerful front-end library developed by Facebook, known for building fast and dynamic user interfaces.

Together, they form a modern tech stack that is performant, scalable, and widely adopted in the industry.

Setting Up the Environment

To get started, you need the following tools installed:

  • Node.js and npm (Node Package Manager)
  • MongoDB (a NoSQL database)
  • Visual Studio Code or your preferred code editor

Check that Node.js and npm are installed by running:

node -v
npm -v
Enter fullscreen mode Exit fullscreen mode

Step 1: Initialize the Project

First, let’s create the backend environment.

mkdir fullstack-app
cd fullstack-app
mkdir backend
cd backend
npm init -y
Enter fullscreen mode Exit fullscreen mode

Install the required packages:

npm install express mongoose cors dotenv
Enter fullscreen mode Exit fullscreen mode
  • Express will be our web framework
  • Mongoose will help us interface with MongoDB
  • CORS is required to allow communication between the frontend and backend
  • dotenv will let us load environment variables securely

Step 2: Create a Basic Express Server

Inside the backend folder, create a file named server.js:

require('dotenv').config();
const express = require('express');
const mongoose = require('mongoose');
const cors = require('cors');

const app = express();

app.use(cors());
app.use(express.json()); // built-in body parser

const PORT = process.env.PORT || 5000;

mongoose.connect(process.env.MONGO_URI, {
  useNewUrlParser: true,
  useUnifiedTopology: true
})
.then(() => console.log('MongoDB connected'))
.catch(err => console.log(err));

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

app.listen(PORT, () => console.log(`Server started on port ${PORT}`));
Enter fullscreen mode Exit fullscreen mode

In your .env file, add your MongoDB connection string:

MONGO_URI=mongodb://localhost:27017/fullstack
Enter fullscreen mode Exit fullscreen mode

Step 3: Define a Mongoose Model

Let’s create a simple model for Task:

Create a file models/Task.js:

const mongoose = require('mongoose');

const TaskSchema = new mongoose.Schema({
  title: {
    type: String,
    required: true
  },
  completed: {
    type: Boolean,
    default: false
  }
});

module.exports = mongoose.model('Task', TaskSchema);
Enter fullscreen mode Exit fullscreen mode

Step 4: Create Routes

Create folder routes and inside taskRoutes.js:

const express = require('express');
const router = express.Router();
const Task = require('../models/Task');

router.get('/', async (req, res) => {
  const tasks = await Task.find();
  res.json(tasks);
});

router.post('/', async (req, res) => {
  const newTask = new Task({
    title: req.body.title
  });
  const savedTask = await newTask.save();
  res.json(savedTask);
});

router.put('/:id', async (req, res) => {
  const updatedTask = await Task.findByIdAndUpdate(req.params.id, req.body, { new: true });
  res.json(updatedTask);
});

router.delete('/:id', async (req, res) => {
  await Task.findByIdAndDelete(req.params.id);
  res.json({ message: 'Task deleted' });
});

module.exports = router;
Enter fullscreen mode Exit fullscreen mode

In server.js, import and use the routes:

const taskRoutes = require('./routes/taskRoutes');
app.use('/api/tasks', taskRoutes);
Enter fullscreen mode Exit fullscreen mode

Step 5: Set Up React Frontend

Go back to the root folder and create the frontend:

npx create-react-app frontend
cd frontend
npm install axios
Enter fullscreen mode Exit fullscreen mode

Step 6: Connect React with Backend

In frontend/src/App.js:

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

function App() {
  const [tasks, setTasks] = useState([]);
  const [title, setTitle] = useState('');

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

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

  const addTask = async () => {
    const res = await axios.post('http://localhost:5000/api/tasks', { title });
    setTasks([...tasks, res.data]);
    setTitle('');
  };

  const deleteTask = async (id) => {
    await axios.delete(`http://localhost:5000/api/tasks/${id}`);
    setTasks(tasks.filter(task => task._id !== id));
  };

  return (
    <div>
      <h1>Task Manager</h1>
      <input value={title} onChange={(e) => setTitle(e.target.value)} />
      <button onClick={addTask}>Add</button>
      <ul>
        {tasks.map(task => (
          <li key={task._id}>
            {task.title}
            <button onClick={() => deleteTask(task._id)}>Delete</button>
          </li>
        ))}
      </ul>
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

Make sure to handle CORS on your Express server if running on different ports (already handled with the cors package).

Step 7: Start Both Servers

In separate terminals:

  • Backend: node backend/server.js
  • Frontend: npm start inside frontend folder

You now have a functional full-stack application where you can add and delete tasks.

Next Steps

Once you’ve mastered the basics, here are some directions to take your project further:

  • Add user authentication (JWT)
  • Deploy the backend with platforms like Heroku or Render
  • Host the frontend using Netlify or Vercel
  • Implement state management with Context API or Redux
  • Add unit testing for your API and components

Conclusion

Building your own full-stack app is a rewarding way to learn key web development skills. With Node.js and React, you’re leveraging two of the most powerful tools available in the JavaScript ecosystem. As you expand and refine your app, you'll naturally deepen your understanding of backend services, frontend reactivity, database management, and much more.

Whether you're preparing for a job in the industry or building your own product, mastering this tech stack will serve you well. Happy coding!

Feel free to drop any questions in the comments or share your own tutorials and creations!

💡 If you need this done – we offer such services: https://ekwoster.dev/service/fullstack-development

Top comments (0)