DEV Community

R Deepti
R Deepti

Posted on

Beyond localhost:3000: How to Finally Connect Your Frontend and Backend

If you're learning full-stack development, you've probably been here before:

You've built a beautiful React frontend. You've created a powerful Express.js backend. You start both servers - frontend on localhost:3000, backend on localhost:5000 - and then... CORS error.

That dreaded red message in the console:

text
Access to fetch at 'http://localhost:5000/api/data' from origin 'http://localhost:3000' has been blocked by CORS policy
Don't worry! This is a rite of passage for every full-stack developer. In this guide, I'll show you three clean ways to connect your frontend and backend, from quick fixes to production-ready solutions.

Understanding the Problem: Why CORS Exists
First, let's understand why this happens. Browsers have a security feature called CORS (Cross-Origin Resource Sharing) that blocks requests between different origins by default.

An "origin" includes the protocol, domain, and port. So:

http://localhost:3000 = one origin

http://localhost:5000 = different origin

The browser blocks your React app from talking to your Express server because they're on different ports. It's a security feature, but in development, it's our biggest headache.

What We're Building
Let's set up a simple example. We have:

Backend (server.js) - Express API on port 5000:

javascript
const express = require('express');
const app = express();
const PORT = 5000;

app.get('/api/books', (req, res) => {
res.json([
{ id: 1, title: 'The Great Gatsby', author: 'F. Scott Fitzgerald' },
{ id: 2, title: 'Dune', author: 'Frank Herbert' }
]);
});

app.listen(PORT, () => {
console.log(Backend running on http://localhost:${PORT});
});
Frontend (App.js) - React app on port 3000 that needs to display the books.

Solution 1: The Proxy Method (Easiest for Development)
If you're using Create React App or Vite, this is the simplest solution.

Step 1: Configure the Proxy
In your frontend's package.json, add this line:

json
{
"name": "my-react-app",
"version": "0.1.0",
"proxy": "http://localhost:5000",
"dependencies": {
// your dependencies
}
}
Step 2: Update Your API Calls
Change your React component to use relative paths instead of the full URL:

javascript
// App.js
import React, { useState, useEffect } from 'react';

function App() {
const [books, setBooks] = useState([]);
const [loading, setLoading] = useState(true);

useEffect(() => {
// Notice: we're using a relative path now
fetch('/api/books')
.then(response => response.json())
.then(data => {
setBooks(data);
setLoading(false);
})
.catch(error => {
console.error('Error fetching books:', error);
setLoading(false);
});
}, []);

if (loading) return

Loading books...;

return (


My Book Collection


    {books.map(book => (
  • {book.title} by {book.author}
  • ))}


);
}

export default App;
How This Works
When your React app makes a request to /api/books, the development server recognizes it's not a static asset and forwards it to http://localhost:5000/api/books. The browser only sees one origin (localhost:3000), so no CORS error!

Restart your frontend server after adding the proxy configuration.

Solution 2: Enable CORS on the Backend (More Flexible)
Sometimes you need more control, or you're not using Create React App. In this case, configure CORS on your Express server.

Step 1: Install the CORS package
bash
cd backend
npm install cors
Step 2: Update Your Server
javascript
const express = require('express');
const cors = require('cors'); // Import the package
const app = express();
const PORT = 5000;

// Enable CORS for all routes
app.use(cors());

// Or be more specific - only allow your frontend
// app.use(cors({
// origin: 'http://localhost:3000'
// }));

app.get('/api/books', (req, res) => {
res.json([
{ id: 1, title: 'The Great Gatsby', author: 'F. Scott Fitzgerald' },
{ id: 2, title: 'Dune', author: 'Frank Herbert' }
]);
});

app.listen(PORT, () => {
console.log(Backend running on http://localhost:${PORT});
});
Step 3: Update Your Frontend (Use Full URL)
Now you can use the full URL in your fetch calls:

javascript
// In your React component
fetch('http://localhost:5000/api/books')
.then(response => response.json())
.then(data => setBooks(data));
Solution 3: Environment Variables (Production Ready)
Hardcoding URLs is bad practice. Let's make this production-ready with environment variables.

Frontend Configuration
Create a .env file in your frontend root:

env

.env in your frontend

REACT_APP_API_URL=http://localhost:5000
Important: Variable names must start with REACT_APP_ for Create React App to recognize them.

Update your React component:

javascript
// App.js
const API_URL = process.env.REACT_APP_API_URL;

useEffect(() => {
fetch(${API_URL}/api/books)
.then(response => response.json())
.then(data => {
setBooks(data);
setLoading(false);
});
}, []);
Backend Configuration
Create a .env file in your backend:

env

.env in your backend

PORT=5000
CLIENT_URL=http://localhost:3000
Update your server to use these variables:

javascript
require('dotenv').config(); // Install with: npm install dotenv

const express = require('express');
const cors = require('cors');
const app = express();
const PORT = process.env.PORT || 5000;

app.use(cors({
origin: process.env.CLIENT_URL
}));

// ... rest of your server code
Putting It All Together: Complete Workflow
Here's my recommended setup for different scenarios:

Development Setup
Use Proxy method for Create React App

Use CORS package for other frontend frameworks

Always use environment variables from day one

Production Setup
Deploy your backend (Heroku, Railway, DigitalOcean)

Deploy your frontend (Netlify, Vercel)

Update your environment variables:

Frontend: REACT_APP_API_URL=https://your-backend.herokuapp.com

Backend: CLIENT_URL=https://your-frontend.netlify.app

Testing Your Connection
Create a simple test to verify everything works:

javascript
// Add this to your backend for testing
app.get('/api/health', (req, res) => {
res.json({ status: 'OK', message: 'Backend is running!' });
});

// Test from your frontend
fetch('/api/health')
.then(response => response.json())
.then(data => console.log('Connection test:', data));

Troubleshooting Common Issues
❌ "Network Error" or CORS block
Fix: Check your proxy setting or CORS configuration

Verify: Backend is running on the correct port

❌ Environment variables not working
Fix: Restart your development server after adding .env files

Verify: Variable names start with REACT_APP_

❌ Proxy not working
Fix: Ensure you're using relative paths (/api/books) not full URLs

Verify: You restarted the frontend after adding the proxy

Next Steps
Now that you've connected your frontend and backend, consider:

Adding error handling to your API calls

Implementing authentication

Setting up a production database

Adding API rate limiting

Conclusion
Connecting frontend and backend doesn't have to be scary. The key takeaways:

Use proxies for simple Create React App setups

Configure CORS when you need more control

Always use environment variables for API URLs

Test your connection before building more features

You've now conquered one of the biggest hurdles in full-stack development. Go build something amazing!

Enjoyed this article? Found another solution that worked for you? Share your experiences and questions in the comments below! Let's learn together. 👇

Top comments (0)