'Axios.post keeps sending empty objects to my API

I am trying to post new information about a cow to my cow API, however, everytime i hit the submit button on my frontend, it seems to be sending an empty object rather than the name of the cow, description of the cow, and image of the cow (via url). What is causing it to send an empty object versus my desired data?

Here is the frontend code:

import React, { useEffect, useState } from 'react';
import axios from 'axios';
import './App.css';
const baseUrl = "http://localhost:3001/api/cows"

function Display({setNameOfCow, setImageOfCow, setDescriptionOfCow, nameOfCow, imageOfCow, descriptionOfCow}) {
  axios.get(baseUrl)
  .then(res => res.data)
  .then(res => {
    setNameOfCow(res.name)
    setImageOfCow(res.image)
    setDescriptionOfCow(res.description)
  })

  return (
    <div>
      <p>{nameOfCow}</p> 
      <img src={imageOfCow}/><p>{descriptionOfCow}</p>
    </div>
  )
}

function Input({setNameOfCow, setImageOfCow, setDescriptionOfCow, nameOfCow, imageOfCow, descriptionOfCow}) {

  function handleSubmit(e) {
    e.preventDefault()
    let newObject = {
      name: nameOfCow,
      description: descriptionOfCow,
      image: imageOfCow
    }

    axios.post(baseUrl, newObject)
  }

  return (
    <div>
      <form>
        <label htmlFor="name">name: </label>
        <input type="text" id="name" onChange={(e) => {
          const eTarget = e.target.value
          setNameOfCow(eTarget)}}/><br></br>
        <label htmlFor="description">description: </label>
        <input type="text" id="description" onChange={(e) => {
          const eTargetDesc = e.target.value
          setDescriptionOfCow(eTargetDesc)}}/><br></br>
        <label htmlFor="image">image url: </label>
        <input type='text' id="image" onChange={(e) => {
          const eTargetImage = e.target.value
          setImageOfCow(eTargetImage)}}/><br></br>
        <button type="submit" onSubmit={handleSubmit}>Add a cow!</button>
      </form>
    </div>
  )
}

function App() {
  const [nameOfCow, setNameOfCow] = useState('')
  const [descriptionOfCow, setDescriptionOfCow] = useState('')
  const [imageOfCow, setImageOfCow] = useState('')

  return (
    <div className="App">
      <Input imageOfCow={imageOfCow} setNameOfCow={setNameOfCow} setDescriptionOfCow={setDescriptionOfCow} setImageOfCow={setImageOfCow} />
      <Display setNameOfCow={setNameOfCow} setImageOfCow={setImageOfCow} setDescriptionOfCow={setDescriptionOfCow} nameOfCow={nameOfCow} imageOfCow={imageOfCow} descriptionOfCow={descriptionOfCow} />
    </div>
  );
}

export default App

and here is the image showing the empty objects being posted:

Empty object being sent to my API



Solution 1:[1]

Looking into your Input component props:

function Input({setNameOfCow, setImageOfCow, setDescriptionOfCow, nameOfCow, imageOfCow, descriptionOfCow}) {...

We can see that you missing to pass this props when using this component:

<Input imageOfCow={imageOfCow} setNameOfCow={setNameOfCow} setDescriptionOfCow={setDescriptionOfCow} setImageOfCow={setImageOfCow} />

The correct way to use is something like:

<Input
    imageOfCow={imageOfCow}
    nameOfCow={nameOfCow}
    descriptionOfCow={descriptionOfCow}
    setNameOfCow={setNameOfCow}
    setDescriptionOfCow={setDescriptionOfCow}
    setImageOfCow={setImageOfCow}
  />

Also the correct way to prevent the form default behavior is setting the onSubmit and the handleSubmit at the form attribute (you can remove from the button):

 <form onSubmit={handleSubmit}>

Otherwise a very nice change is to put your axios request inside a useEffect hook to prevent your app from making request every time it re-render. Using something like this the app will make the request only at the first component render.

  const getCow = async (baseUrl) => {
    const cow = await axios.get(baseUrl);

    setNameOfCow(cow.name);
    setImageOfCow(cow.image);
    setDescriptionOfCow(cow.description);
  };

  useEffect(() => {
    getCow(baseUrl);
  }, []);

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Ruan