Search code examples
reactjsfetch-api

Multiple async fetch requests causes function to hang execution


I have a signup component that executes 2 requests from 2 functions, one that inserts user data in the database and returns the inserted user id if the request is successful, otherwise it returns false, the other one checks the returned id, if exist, it takes the id and the image url after uploading image to firebase and updates the user url in the database, However the code navigate("/email-approval") doesn't execute, actually nothing executes in that else block of code, inspecting the requests in the network tab, the upload-user-image actually does upload the image but the status of the request is pending for quite long time or maybe it stays pending forever, why does it stops execution although its asynchronous ?

   const uploadUser = async () => {
    setDisableBtn(true);
    const user = {
      firstName: userData.firstName,
      lastName: userData.lastName,
      email: `${userData.email}@bushnaq.group`,
      password: userData.password,
      gender: userData.gender,
      birthDate: userData.birthDate,
      image: "placeholder",
    };

    const res = await fetch("http://localhost:8000/api/signup", {
      method: "POST",
      body: JSON.stringify(user),
      headers: { "Content-Type": "application/json" },
    });
    const data = await res.json();
    if (data.status === 400) {
      setDisableBtn(false);
      setErrSignup(data.message);
      return false;
    }
    return data.id;
  };

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

    let errors = {};

    if (
      userData.image.type !== "image/jpeg" &&
      userData.image.type !== "image/png"
    ) {
      errors.errImg = "Profile picture must have JPEG or PNG extensions.";
    }

    if (
      userData.firstName.length > 15 ||
      userData.lastName.length > 15 ||
      userData.firstName.length < 3 ||
      userData.lastName.length < 3
    ) {
      errors.errName =
        "First name and/or must be between 3 and 15 characters in length.";
    }
    if (userData.email.length > 25) {
      errors.errEmail = "Email is too long.";
    }

    if (userData.email.includes("@")) {
      errors.errEmail = "Email must not contain @ sign.";
    }

    if (!isPasswordStrong(userData.password)) {
      errors.errPs =
        "Please use a password that contains at least one number, one uppercase letter and at least 8 chatacters in length.";
    }

    if (userData.password !== userData.confirmPassword) {
      errors.errCp = "Passwords do not match.";
    }

    if (!userData.gender) {
      errors.errGender = "Gender must not be empty.";
    }

    setErrors(errors);

    if (!Object.keys(errors).length) {
      const id = await uploadUser();
      if (id) {
        const imageRef = storageRef(storage, `images/${Date.now()}`);
        const snapshot = await uploadBytes(imageRef, userData.image);
        const url = await getDownloadURL(snapshot.ref);
        const res = await fetch("http://localhost:8000/api/upload-user-image", {
          method: "PUT",
          body: JSON.stringify({
            id: id,
            url: url,
          }),
          headers: { "Content-Type": "application/json" },
        });
        const data = await res.json();
        if (data.status === 400) {
          setErrSignup(data.message);
        } else {
          console.log("done");
          navigate("/email-approval");
        }
      }
    }
  };

Solution

  • You don't have status on data variable after await res.json(). You should check res.ok or res.status and after that do this res.json(). PLease check the docs https://developer.mozilla.org/en-US/docs/Web/API/Response Modified example:

    const handleSubmit = async (e) => {
      e.preventDefault();
    
      let errors = {};
    
      if (
        userData.image.type !== 'image/jpeg' &&
        userData.image.type !== 'image/png'
      ) {
        errors.errImg = 'Profile picture must have JPEG or PNG extensions.';
      }
    
      if (
        userData.firstName.length > 15 ||
        userData.lastName.length > 15 ||
        userData.firstName.length < 3 ||
        userData.lastName.length < 3
      ) {
        errors.errName =
          'First name and/or must be between 3 and 15 characters in length.';
      }
      if (userData.email.length > 25) {
        errors.errEmail = 'Email is too long.';
      }
    
      if (userData.email.includes('@')) {
        errors.errEmail = 'Email must not contain @ sign.';
      }
    
      if (!isPasswordStrong(userData.password)) {
        errors.errPs =
          'Please use a password that contains at least one number, one uppercase letter and at least 8 chatacters in length.';
      }
    
      if (userData.password !== userData.confirmPassword) {
        errors.errCp = 'Passwords do not match.';
      }
    
      if (!userData.gender) {
        errors.errGender = 'Gender must not be empty.';
      }
    
      setErrors(errors);
    
      if (Object.keys(errors).length > 0) {
        return;
      }
    
      try {
        const id = await uploadUser();
        if (id) {
          const imageRef = storageRef(storage, `images/${Date.now()}`);
          const snapshot = await uploadBytes(imageRef, userData.image);
          const url = await getDownloadURL(snapshot.ref);
          const res = await fetch('http://localhost:8000/api/upload-user-image', {
            method: 'PUT',
            body: JSON.stringify({
              id: id,
              url: url,
            }),
            headers: { 'Content-Type': 'application/json' },
          });
          const data = await res.json();
    
          if (res.status === 400) {
            return setErrSignup(data.message);
          }
    
          console.log('done');
          navigate('/email-approval');
        }
      } catch (error) {
        console.log(error);
      }
    };