Why could I not get my backend file, server.js, to connect to a front-end?Error: POST http://localhost:3000/api/person/add 400 (Bad Request)?

Viewed 60

My server side file, this is the server.js file This is me require the packages for my backend file

require("dotenv").config();
const express  = require("express");
const mongoose = require("mongoose");
// const cors     = require("cors");
const path     = require("path");
const app      = express();
 

This is where I deal with the mongodb

// const PORT     = process.env.PORT || 4000;
const DB_URI   = "mongodb://localhost:27017/"
const DB       = "reactDB";
 
// Middleware
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
// app.use(cors());
 
// Establish DB connection
mongoose.connect(DB_URI + DB, {
   useUnifiedTopology: true,
   useNewUrlParser: true,
   useCreateIndex: true,
   useFindAndModify: false,
   connectTimeoutMS: 10000
});
 
const db = mongoose.connection;
 
// Event listeners
db.once('open', () => console.log(`Connected to ${DB} database`));
 
// Create Schema
let PersonSchema = new mongoose.Schema(
   {
      forename: String,
      age: Number
   },
   { collection: "people" }
);
 
// Create Model
let PersonModel = db.model("PersonModel", PersonSchema);
 
// Route to Get all People

Since, the error is getting post request error, it could be something here as well.

app.get("/api/people", (req, res) => {
   PersonModel.find({}, {__v: 0}, (err, docs) => {
      if (!err) {
         res.json(docs);
      } else {
         res.status(400).json({"error": err});
      }
   });
})

I cannot get this post request to get handled. I don't know why?

// Route to Add a Person
app.post("/api/person/add", (req, res) => {
   let person = new PersonModel(req.body);
   
   person.save((err, result) => {
      if (!err) {
        //   console.log("The result._doc.__v is "+result._doc.__v);
         delete result._doc.__v;
         res.json(result._doc);
        //  console.log("The result._doc is " + result._doc);
      } else {
         res.status(400).json({"error": err});
      }
   });
})
 
app.listen(4000, () => {
   console.log(app.get("env").toUpperCase() + " Server started on port " );
});

The front-end is created by React, and all the input are showing, but when I click the add button, everything that I have typed disappear.

Here is the frontend file.

import React, { useState, useEffect } from "react";
import Person from "./Person";
import axios from "axios";
 
/*** Remember that the proxy to the backend server is http://localhost:4747 ***/
 
const defaultPerson = {
  forename: "",
  age: "",
};
 
function App() {
  const [person, setPerson] = useState(defaultPerson);
  const [people, setPeople] = useState([]);
 
  /*
    Fetch all People the moment this App component loads for the first time
    Notes: The proxy enables us to use axios without the full url http://localhost:4747/api/people
           The empty array [] parameter ensures that the code inside useEffect() runs once
  */
  useEffect(() => {
    axios.get("/api/people")
      
      .then((res) => setPeople(res.data))
      
      .catch((err) => console.error(err));
  }, []);
 
  function handleChange(event) {
    const { name, value } = event.target;
 
    setPerson({ ...person, [name]: value });
  }
 
  /*
    Add a person to DB and update state
    Notes: The proxy enables us to use axios without the full url http://localhost:4747/api/person/add
  */
  function addPerson(newPerson) {
    axios.post("/api/person/add", newPerson)
      .then((res) => setPeople([...people, res.data]))
      .catch((err) => console.log(err));
  }
 
  return (
    <>
      <form onSubmit={(e) => e.preventDefault()}>
        <input
          name="forename"
          type="text"
          placeholder="Enter your Forename"
          value={person.forename}
          onChange={handleChange}
        />
        <input
          name="age"
          type="text"
          placeholder="Age"
          value={person.age}
          onChange={handleChange}
        />
        <button
          onClick={() => {
            if (person.forename && person.age) {
              addPerson(person);
              setPerson(defaultPerson);
            }
          }}
        >
          Add
        </button>
        {people.map((person) => (
          <Person
            key     ={person._id}
            _id     ={person._id}
            forename={person.forename}
            age     ={person.age}
          />
        ))}
      </form>
    </>
  );
}
 
export default App;
2 Answers

You are listening to port 4000. Either change this to port 3000, or in your URL use :4000.

You are not telling your react app where to do the endpoint call - so it is using itself as reference. That is why, as you started the React App in port 3000, axios makes all calls to localhost:3000

One solution to this, if you are using Create React App, is to add in your package.json the following line: “proxy”: “http://localhost:4000”. Otherwise, you'll need to give the entire data to axios, like axios.get(http://localhost:4000/api/people; or look different ways of proxying your app and the server.

Related