Search code examples
reactjsaxioscloudinaryreact-dropzone

REACT, Axios, cloudinary push mutliple secure_urls Into State Array In Reactjs


I have been trying to push secure_urls from Cloudinary data response to React state Array with no success. When I add a new Image to the dropzoneArea, the previous urls are added to the array, hence duplicating urls. Does anyone have an idea how to approach this?

State

 const [fileItems, setFileItems] = useState([]);

DropZone

<DropzoneArea
      acceptedFiles={["image/jpeg", "image/png", "image/bmp", "image/jpg"]}
      onChange={handleFiles}
      onDelete={handleDeleteFile}
      showFileNames
      filesLimit={5}
    />
const handleFiles = (files) => {
    files.forEach((file) => {
      const formData = new FormData();
      formData.append("file", file);

      formData.append("upload_preset", process.env.REACT_APP_UPLOAD_PRESET);

      return Axios.post(
        `https://api.cloudinary.com/v1_1/${process.env.REACT_APP_CLOUD_NAME}/upload`,
        formData,
        {
          headers: { "X-Requested-With": "XMLHttpRequest" },
        }
      )
        .then((res) => {
          const fileUrls = res.data.secure_url;
          setFileItems(fileItems=>[...fileItems,fileUrls])
        })
        .catch((err) => {
          console.log(err.message);
        });
    });
  };

Solution

  • I see multiple problems with your code. For starters, you have a shadowed variable name, see the duplication of fileItems

    const [fileItems, setFileItems] = useState([]);
    ...
    setFileItems(fileItems=>[...fileItems,fileUrls])
    

    Also, calling setState inside a loop is an anti-pattern. You could try to refactor your code something like this:

    const handleFiles = (files) => {
        const fileUrlArray = [];
        files.forEach((file) => {
          const formData = new FormData();
          formData.append("file", file);
    
          formData.append("upload_preset", process.env.REACT_APP_UPLOAD_PRESET);
    
          return Axios.post(
            `https://api.cloudinary.com/v1_1/${process.env.REACT_APP_CLOUD_NAME}/upload`,
            formData,
            {
              headers: { "X-Requested-With": "XMLHttpRequest" },
            }
          )
            .then((res) => {
              const fileUrls = res.data.secure_url;
              fileUrlArray.push(fileUrls);
            })
            .catch((err) => {
              console.log(err.message);
            });
        });
        setFileItems(prevState => [...prevState, ...fileUrlArray])
      };
    

    Not sure if it'll fix your code, but this is something to start on.