简体   繁体   中英

React-native Cloudinary image upload problem with state

I am building an app with react-native and EXPO CLI, and I have a screen which I am fetching an image/several images from a user in the registration process. I want to fetch the image from the user's gallery, then upload it to cloudinary and generate a url, and then push this url into the Database and render it on the screen after.

The images are being uploaded to Cloudinary successfully, but it doesn't return the url in time, resolving in the 'imagesUrl' state to be empty when I push the data into the Database. So basically after a while in Cloudinary I see my images, but In the database under the "images" field, I get an empty array, which is being set to a state which is also empty at the time. The setState is not working properly.

My code:

Local states:

  const [images, setImages] = useState([]);

  const [imagesUrl, setImagesUrl] = useState([]);

Function responsible for picking an image from a user's gallery:

 const pickImage = async () => {
    let result = await ImagePicker.launchImageLibraryAsync({
      mediaTypes: ImagePicker.MediaTypeOptions.All,
      allowsEditing: true,
      aspect: [4, 3],
      quality: 1,
    });

    if (!result.cancelled) {
      if (images.length < 6) setImages((prev) => [...prev, result]);
    }
  };

Function responsible for uploading to Cloudinary:

 const handleUploads = async (files) => {
    const formData = new FormData();

    for (let i = 0; i <= files.length; i++) {
      let file = files[i];
      formData.append("file", file);
      formData.append("upload_preset", "wingman");
      formData.append("cloud_name", "drsgaixjb");

      const res = await fetch(`${CLOUDINARY_URL}/image/upload`, {
        method: "POST",
        body: formData,
      });

      const cloudinaryFiles = await res.json();
      setImagesUrl([...imagesUrl, cloudinaryFiles.url]);
    }
  };

Function responsible to convert the files that the user upload to the right type:

 const handleImagesType = (imgs) => {
    let newImages = [];
    imgs.forEach((img) => {
      newImages.push({
        uri: img.uri,
        type: `test/${img.uri.split(".")[1]}`,
        name: `test/${img.uri.split(".")[1]}`,
      });
    });
    return newImages;
  };

And the last function which is responsible of pushing the data into the database:

  const pushDataHandler = async (data) => {
    if (data.length) {
      const temp = handleImagesType(data);
      handleUploads(temp);
      await db.collection("users").doc(firebase.auth().currentUser.uid).update({
        images: imagesUrl,
      });
    }
  };

When the user presses the button to submit the images:

  onPress={() => {
            pushDataHandler(images);
            dispatch(pullUserData()); //Pulling all the data of a user from DB to a redux state
  }}

Here is a complete example that was done by OGcodes using the direct call to Cloudinary Rest API together with the ImagePicker component .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM