Wulfyyyy
Wulfyyyy

Reputation: 13

my function is having an asynchronous issue, when uploading file to firebase. can anyone explain why?

Currently my app has an upload button, that when clicked will upload file to firebase and grab download url. and save it to a state variable. Then a second button to submit the form as a whole and send it to db(currently just console.logs(userInput state) to show what it would send.

However, currently what i am trying to write is a function that will in one click. upload file, grab url, save to state and return / console.log(userInput). All in one button click.

However it takes two clicks for the fuction to actually update the user input variable with the image url. I can't figure out why. My current guess has to do with it being returned as a promise. the console.log fires first and then it saves to state, hence it working on the second click.

What am i doing incorrectly? or what do i need to research more of?

function App() {
  const [imgUpload, setImageUpload] = useState(null);
  const [downloadUrl, setDownloadUrl] = useState("");
  const [userInput, setUserInput] = useState({
    first_name: "",
    last_name: "",
    email: "",
    userImg: "",
  });

  const handleChange = (e) => {
    setUserInput((prevInput) => ({
      ...prevInput,
      [e.target.name]: e.target.value,
    }));
  };
 
  async function handleUpload(file) {
    const storageRef = ref(storage, `employees/${file}`);
    const uploadTask = uploadBytes(storageRef, file);

    const downUrl = await getDownloadURL((await uploadTask).ref);
    setUserInput((prevInput) => ({
      ...prevInput,
      userImg: downUrl,
    }));
    console.log(downUrl);
  }

  function handleSubmit() {
    console.log("submit", userInput);
  }
  console.log("state", downloadUrl);
  return (
    <div className="App">
      <input
        type="file"
        name="img"
        onChange={(e) => setImageUpload(e.target.files[0])}
      />
      <button onClick={() => handleUpload(imgUpload)}>Upload image</button>
      <input type="text" name="first_name" onChange={handleChange} />
      <input type="text" name="last_name" onChange={handleChange} />
      <button
        onClick={() => {
          handleSubmit();
        }}
      >
        submit
      </button>
    </div>

Upvotes: 0

Views: 68

Answers (1)

Doug Stevenson
Doug Stevenson

Reputation: 317497

uploadBytes returns a promise, but your code is ignoring it and moving along before the upload completes. Perhaps you should await it:

    const uploadTask = await uploadBytes(storageRef, file);

See also:

Upvotes: 0

Related Questions