yuroni
yuroni

Reputation: 65

formData cannot arrive to backend

I'm trying to make a team section, that it is a dynamic form. You can insert team members as much as you want, and it includes, "memberName", "memberDescription", "memberJobTitle", "images".

Really do not understand why but something is wrong in the frontend, somehow file does not arrive to backend, when I submit to create a team member, I got this message:

message: "Cannot read properties of undefined (reading 'path')

However,

  1. When I try upload file to team member on Postman with form-data, it works. So, I assume problem is not in the backend.

    team[0][memberName]: "Lala" team[0][memberJobTitle]: "Lala" team[0][images][0]: "image.jpg" team[0][memberDescription]: "Lala"

  2. In the frontend, I can see the file that I uploaded when I submit in console.log(values).

    team: Array(1) 0: images:Array(1) 0: FileList {0: File, length: 1} length: 1 [[Prototype]]: Array(0) memberDescription: "work with us 5 years long" memberJobTitle: "marketing" memberName: "Jane Doe"

  3. If I log console.log("append image: ", item.images[0]); it also shows me a FileList.

    FileList {0: File, length: 1} 0: File {name: 'real-estate-logo-template_1195-19.jpg.webp', lastModified: 1672667306966, lastModifiedDate: Mon Jan 02 2023 13:48:26 GMT+0000 (Western European Standard Time), webkitRelativePath: '', size: 9894, …} length: 1

submitHandler

const submitHandler = async (values) => {
    const formData = new FormData();

    // append other fields

    values.team = values.team || [{}];

    values.team.forEach((item, index) => {
      formData.append(`team[${index}][memberName]`, item.memberName || "");
      //append other team fields

      formData.append(`team[${index}][images][0]`, item.images[0]);

      console.log("append image: ", item.images[0]);
    });


    await axios({
      method: "POST",
      url: `http://localhost:8080/api/pages/${pageId}/aditional-section`,
      data: formData,
      headers: {
        "Content-Type": "multipart/form-data",
        Authorization: "Bearer " + localStorage.getItem("token"),
      },
    })
      .then((res) => {
        console.log(res);
      })
      .catch((res) => {
        console.log(res);
      });

    console.log(values);
  };

I'm using Formik to handle form.

     <FieldArray name="team">
    {({ insert, remove, push }) => (
      <div>
        {values.team.length > 0 &&
          values.team.map((item, index) => (
            <div className="row" key={index}>
              <div className="col">
                <label htmlFor={`team.${index}.images[0]`}>
                  Upload image
                </label>

                {/* <Field
                  name={`team.${index}.images`}
                  type="file"
                /> */}

                <FileInput
                  name={`team.${index}.images[0]`}
                  type="file"
                  value={undefined}
                />

                <ErrorMessage
                  name={`team.${index}.images[0]`}
                  component="div"
                  className="field-error"
                />
              </div>
            </div>
          ))}
        <button
          type="button"
          className="secondary"
          onClick={() =>
            push({
              memberName: "",
              memberJobTitle: "",
              memberDescription: "",
              images: "",
            })
          }
        >
          Add Member
        </button>
      </div>
    )}
</FieldArray>

Upvotes: 2

Views: 530

Answers (1)

Chris Warren
Chris Warren

Reputation: 88

MDN Docs states:

value

The field's value. This can be a string or Blob (including subclasses such as File). If none of these are specified the value is converted to a string.

It appears that the FileList type isn't supported but the File type is. Try looping through the FileList and appending each file to the formData like so.

const submitHandler = async (values) => {
    ...

    values.team.forEach((item, index) => {
      formData.append(`team[${index}][memberName]`, item.memberName || "");
      //append other team fields
      // Before
      // formData.append(`team[${index}][images][0]`, item.images[0]);
      
      // After - Loop through images, and append the File
      for (let i = 0; i < item.images[0].length; i++) {
         const file = item.images[0].files[i];
         formData.append(`team[${index}][images][0]`, file);
      }

      console.log("append image: ", item.images[0]);
    });


    ...
  };

This should work, granted your backend is set up to receive multiple files.

Upvotes: 2

Related Questions