0

I am getting this in the browser console:

`xhr.js:251     POST http://localhost:325/budget 400 (Bad Request)

BudgetNew.js:30 catch AxiosError {message: 'Request failed with status code 400', name: 'AxiosError', code: 'ERR_BAD_REQUEST', config: {…}, request: XMLHttpRequest, …}`

Here is my server side code:

budget_controller:

//DEPENDENCIES
const express = require("express");
const budget = express.Router();
const budgetArray = require("../models/budget_table.js");
const { validateBudgetData } = require("../models/validations.js");

//CONFIGURATION
budget.get('/', (req, res) => {
    res.json(budgetArray);
});
/* this route is triggered when a "GET" request is made to the base URL ("/budget"). It responds by sending the entire budgetArrau as a JSON in the res body - this retrieves a list of items in the budget array
*/

//with error handling:
budget.get("/:arrayIndex", (req,res) => {
    if(budgetArray[req.params.arrayIndex]) {
        res.json(budgetArray[req.params.arrayIndex]);
    } else {
        res.status(404).json({error: "Not Found"});
    }
});

budget.post("/", validateBudgetData, (req, res) => {
    budgetArray.push(req.body);
    res.json(budgetArray[budgetArray.length - 1])
});


//DELETE with error handling
budget.delete("/:indexArray", (req, res) => {
    if (budgetArray[req.params.indexArray]) {
        const deletedItem = budgetArray.splice(req.params.indexArray, 1);
        res.status(200).json(deletedItem);
    } else {
        res.status(404).json({ error: "Not Found" });
    }
})

//UPDATE/change already existing data (HTTP verb PUT) with error handling
budget.put("/:arrayIndex", validateBudgetData, async (req, res) => {
    if (budgetArray[req.params.arrayIndex]) {
        budgetArray[req.params.arrayIndex] = req.body; 
        res.status(200).json(budgetArray[req.params.arrayIndex]);
    } else {
        res.status(404).json({ error: "Not found" })
    }
});



//EXPORT
module.exports = budget;

validations:

    const validateBudgetData = (req, res, next) => {
    const { item_name, amount, deduction, date, category } = req.body;

    if (
        typeof item_name === 'string' &&
        typeof amount === 'number' &&
        typeof deduction === 'boolean' &&
        typeof date === 'string' &&
        typeof category === 'string'
    ) {
        return next();
    } else {
        res.status(400).send("Invalid budget data");
    }
};

//EXPORT
module.exports = { validateBudgetData };

REACT BudgetNew Component

import { useState } from "react";
import { useNavigate, Link, useParams } from "react-router-dom";
import axios from "axios";

export default function BudgetNew() {
    const API = process.env.REACT_APP_API_URL;
    const navigate = useNavigate();
    const { index } = useParams(); //Get the index parameter from the URL
    const [transaction, setTransaction] = useState({
        item_name: "",
        amount: 0,
        date: "",
        deduction: false,
        category: "",
    });

    const handleTextChange = (e) => {
        setTransaction({ ...transaction, [e.target.id]: e.target.value });
    };

    const handleCheckboxChange = () => {
        setTransaction({ ...transaction, deduction: !transaction.deduction });
    };

    const addTransaction = (newTransaction) => {
        axios
        .post(`${API}/budget`, newTransaction)
        .then(() => {
            navigate("/budget");
        })
        .catch((c) => console.error("catch", c));
    };
    /* the addTransaction fxn takes 2 parameters:
    // 1.the URL where the request will be sent 
    // 2. newTransaction, a variable that represents the data of the new transaction to be added to the server
    // */

    const handleSubmit = (e) => {
        e.preventDefault();
        addTransaction(transaction);
        //call the addTransaction fxn with the transaction data and not "newTransaction" because the form data is stored in transaction from our useState fxn not "newTransaction". So, when we want to call the addTransaction fxn, we should pass the transaction data as an argument.
    }

    return (
            <div className="Edit">
                <form onSubmit={handleSubmit}>
                    <label htmlFor="name">Name:</label>
                    <input
                        id="item_name"
                        value={transaction.item_name}
                        type="text"
                        onChange={handleTextChange}
                        placeholder="Item name"
                        required
                    />
                    <label htmlFor="amount">Amout:</label>
                    <input
                        id="amount"
                        value={transaction.amount}
                        type="number"
                        onChange={handleTextChange}
                        placeholder="Enter amount"
                        required
                    />
                    <label htmlFor="deduction">Is this transaction a deduction?</label>
                    <p>Does this take away from total income? If yes, check the box. If no, leave box unchecked.</p>
                    <input
                        id="deduction"
                        value={transaction.deduction}
                        type="checkbox"
                        onChange={handleCheckboxChange}
                    />
                    <br />

                    <label htmlFor="date">Date:</label>
                    <p>Enter as mm/dd/yyyy</p>
                    <input
                        id="date"
                        value={transaction.date}
                        type="text"
                        onChange={handleTextChange}
                        placeholder="Date of transaction"
                        // required
                    />
                    <label htmlFor="category">Category: </label>
                    <input
                        id="category"
                        value={transaction.category}
                        type="text"
                        onChange={handleTextChange}
                        placeholder="What is this for?"
                        required
                    />
                    <br />
    
                    <input type="submit" />
                </form>
                <Link to={`/budget/${index}`}>
                    <button>Nevermind!</button>
                </Link>
            </div>
    );
}

I tried restarting the starting and react app. I reviewed my code. I commented out my "addTransaction" fxn in the BudgetNew component and added this code:

const requestData = {
    item_name: "Cash",
    amount: 100,
    deduction: false,
    date: "07/30/23",
    category: "income"
};

axios.post(`${API}/budget`, requestData)
    .then((response) => {
        console.log("Success:", response.data);
    })
    .catch((error) => {
        console.log("Error:", error.response.data);
    });

This worked, which hinted the server side was not the problem, but I am still getting the error.

halfer
  • 19,824
  • 17
  • 99
  • 186
Noni P.
  • 11
  • 2

1 Answers1

0

First question:

Can I see your .env file?

The error you posted has reference to the API variable, which is defined by your "REACT_APP_API_URL" variable in your .env file.

Are you really running the app on localhost:325 ?

Just curious, I have never ran a react app or a server on that port.

I would double check that the value you have for REACT_APP_API_URL is correct in your .env for your client (I assume you have a separate .env file for your client and server)

Without seeing the .env file, it is hard to tell what your error is really coming from.

edit: the reasons I think this might be the problem is the error message states it is a bad request, so it seems like your request didn't even make it to your server.

J Wylie
  • 1
  • 2
  • Sorry for posting an answer instead of commenting on your question, stack overflow said I do not have enough reputation to add comments to other people's questions. – J Wylie Aug 22 '23 at 03:27
  • Hello, my PORT=0325. I think I fixed it. I debugged by plugging in one field at a time on the form and I found that I came across the error when putting the amount. It was because event.target.value was returning the data as a string instead of a number. However, in my validations file I am expecting a number not a string. So I am using parseFloat(value). But the error is still a wonder to me because I was getting it for a different issue early on before I changed my validations file in the server side. Thank you for your response! – Noni P. Aug 22 '23 at 17:09