1
const AddNew = (props) => {
  const [photoUrl, setPhotoUrl] = useState([]);
  const [title, setTitle] = useState();
  const [photos, setPhotos] = useState([]);

  useEffect(() => {
    axios.get("http://localhost:80/newItem").then((res) => {
      console.log(res.data);
    });
  });
  const uploadPhoto = () => {
    console.log("one");
    const storage = fire.storage();
    const reference = storage.ref();
    photos.forEach((photo) => {
      reference
        .child(photo.name)
        .put(photo)
        .then(
          (snapShot) => {
            snapShot.ref.getDownloadURL().then((url) => {
              console.log(url);
              setPhotoUrl((photoUrl) => [...photoUrl, url]);
            });
          },

          (err) => {
            console.log(err);
          }
        );
    });
  };

  const addItems = () => {
    console.log("two");
    const photo = photoUrl;
    const uploadData = axios
      .post("http://localhost:80/newItem", {
        photos: photo,
        title: title,
      })
      .then((res) => alert(res))
      .catch((e) => alert(e));
    window.location.reload(false);
  };
  const uploadData = async () => {
    await uploadPhoto;
    await addItems;
  };
  return (
    <div>
      <Container>
        <h4
          className="text-center mb-5 mt-5"
          style={{ borderBottom: "1px solid black" }}
        >
          Add a new Product
        </h4>
        <div style={{ width: "75%", margin: "0 auto" }}>
          <Row className="text-center">
            <Col sm={12} lg={12} md={12}>
              <Form.Group>
                <Form.File
                  label="upload upto 5 images"
                  multiple
                  onChange={(e) => {
                    if (Array.from(e.target.files).length <= 4) {
                      const img = Array.from(e.target.files);
                      setPhotos(img);
                    } else {
                      alert("You can select maximum 5 Images");
                      e.target.value = null;
                    }
                  }}
                  accept=".jpg"
                />
              </Form.Group>
              <Form.Group controlId="exampleForm.ControlInput1">
                <Form.Label>Title</Form.Label>
                <Form.Control
                  type="text"
                  placeholder="Title"
                  value={title}
                  onChange={(e) => setTitle(e.target.value)}
                />
              </Form.Group>

              <Button variant="outline-primary" onClick={uploadData}>
                Submit
              </Button>
            </Col>
          </Row>
        </div>
      </Container>
    </div>
  );
};
export default AddNew;

In the above code On click of button, I'm going to uploadData function. Where in uploadData function, the uploadPhoto function should execute first and then it should set the URL to the setPhotoUrl hook. And after storing the image and getting the url, addItems function should execute where it posts the title and url of photo to the express server. But it is not happening as expected.

3
  • Your uploadPhoto and addItems methods don't return a promise, so it has nothing to wait for. Commented Sep 23, 2020 at 8:22
  • I guess you would also have to convert the ´photos.forEach` method from a promise chain to an async function. Commented Sep 23, 2020 at 9:06
  • @Gh05d How to do that sir? since I' a young developer i'm unble to do this... can you please explain me everything with piece of above code? Commented Sep 23, 2020 at 9:15

2 Answers 2

1

You can wrap your addItems method's invocation inside a useEffect and conditionally fire it only if you have set photoUrl and title.

useEffect(()=>{
 if(title && photoUrl)
 addItems();
},[title,photoUrl])

After this, you should set your title and photoUrl back to an empty string or null. So inside your addItems method add the following line

 const addItems = () => {
    console.log("two");
    const photo = photoUrl;
    const uploadData = axios
      .post("http://localhost:80/newItem", {
        photos: photo,
        title: title,
      })
      .then((res) =>{ 
            alert(JSON.stringify(res))
            setPhotoUrl('');
            setTitle('');
      })
      .catch((e) => alert(e));
    window.location.reload(false);
  };
Sign up to request clarification or add additional context in comments.

4 Comments

Sir, on click of submit button it should execute functions one by one
Then you should return promises from both the functions so you can chain your methods.
Sir how to do that? Could you please explain me with the above peace of code? I did that but before clicking submit button only images are getting uploaded
You are setting state which itself is an async operation. Even if you do return a promise from the first function, by the time you run the second function setState might have not invoked and your state might be null at that point. The only way to track it is using useEffect. That approach makes sure you call your addItems only when you have your state variables set that you are required to send back to the server.
0

You have to convert your functions to async functions in order to be able to await them. So do instead of

const uploadPhoto = () => { and const addItems = () => {

this const uploadPhoto = async () => { and this const addItems = async() => {

Then change your uploadData function to this:

  const uploadData = async () => {
    await uploadPhoto();
    await addItems();
  };

1 Comment

Sir I did like that but Images are getting uploaded later, after function got finished

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.