Search code examples
postnext.jsaxiosstrapi

Axios Error: Request failed with status code 400 when sending a POST request in React using Axios


I'm building a React application and trying to send a POST request to my Strapi backend API using Axios. However, I'm encountering the following error:

{
  "message": "Request failed with status code 400",
  "name": "AxiosError",
  "stack": "...",
  "config": {
    "transitional": { ... },
    "adapter": [ ... ],
    "transformRequest": [ ... ],
    "transformResponse": [ ... ],
    "timeout": 0,
    "xsrfCookieName": "XSRF-TOKEN",
    "xsrfHeaderName": "X-XSRF-TOKEN",
    "maxContentLength": -1,
    "maxBodyLength": -1,
    "env": { ... },
    "headers": { ... },
    "method": "post",
    "url": "http://localhost:1337/api/products",
    "data": { ... }
  },
  "code": "ERR_BAD_REQUEST",
  "status": 400
}

Here's the relevant part of my React code:

const [name, setName] = useState("");
const [description, setDescription] = useState("");
const [image, setImage] = useState("");
const [price, setPrice] = useState("");
const [brand, setBrand] = useState("");

const handleSubmit = async (e) => {
  e.preventDefault();

  axios
    .post(process.env.NEXT_PUBLIC_API_URL + "/products", {
      "data": {
        "name": name,
        "description": description,
        "image": image,
        "price": price,
        "brand": brand
      },
    })
    .then((response) => {
      console.log(response);
    })
    .catch((error) => {
      setError(error);
      console.log(error);
    });
};

I've checked the API URL, and it seems to be correct. The request payload also appears to be valid JSON. However, I'm still getting a 400 Bad Request error. Can someone please help me understand what might be causing this issue and how to resolve it?

EDIT: I did some more research and it looks like im getting the error when i try to POST a image url. I tried leaving the image null and i got a 200.

{
"data": null,
"error": {
    "status": 400,
    "name": "ValidationError",
    "message": "1 relation(s) of type plugin::upload.file associated with this entity do not exist",
    "details": {
        "errors": [
            {
                "path": [],
                "message": "1 relation(s) of type plugin::upload.file associated with this entity do not exist",
                "name": "ValidationError"
            }
        ]
    }
}

}


Solution

  • Finally figured out the solution. For anyone interested below:

    1. Uploading the Image to Strapi Backend: First, you need to upload your image to the Strapi backend. This is done using the image's URL. Essentially, you're telling Strapi where the image is located on the internet so that it can retrieve and store it.

    2. Connecting the Image to the Product: Once the image is uploaded, the next step is to associate it with a specific product in your Strapi database. This means that when someone views the product in your application or website, they will also see the image you've uploaded. You perform this association in the same form where you created the product. It's like adding a picture to a product listing to make it more appealing and informative to users.

    3. Integrated Process: The key point here is that both the image upload and linking it to the product happen through the same form. This integration simplifies the process, allowing you to handle both tasks - creating a product and attaching an image to it - in one go.

    Here is the code:

    const [name, setName] = useState("");
      const [description, setDescription] = useState("");
      const [imageURL, setImageURL] = useState("");
      const [price, setPrice] = useState("");
    
      const uploadImage = async (imageUrl) => {
        try {
          const imageResponse = await fetch(imageUrl);
          const imageBlob = await imageResponse.blob();
    
          const formData = new FormData();
          formData.append('files', imageBlob, imageUrl);
    
          const uploadResponse = await axios.post(`${process.env.NEXT_PUBLIC_API_URL}/upload`, formData, {
            headers: {
              'Content-Type': 'multipart/form-data'
            }
          });
          return uploadResponse.data[0].id;
        } catch (error) {
          setError(error);
          console.error("Error uploading image:", error);
          return null;
        }
      };
    
      const handleSubmit = async (e) => {
        e.preventDefault();
    
        const uploadedImageId = await uploadImage(imageURL);
        
        if (uploadedImageId) 
        {
          axios.post(`${process.env.NEXT_PUBLIC_API_URL}/products`, {
            data: {
              name: name,
              description: description,
              image: uploadedImageId,
              price: price,
            },
          })
          .then(response => {
            console.log('Product created:', response);
          })
          .catch(error => {
            setError(error);
            console.error('Error creating product:', error);
          });
        }
      };
            <label class="block mb-2 font-medium text-gray-900 dark:text-white">
              Image (URL)
            </label>
            <input
              type="text"
              class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
              placeholder="Url"
              name="image"
              onChange={e => setImageURL(e.target.value)}
              value={imageURL}
              required
            />
          </div>