reactjsfunctiongoogle-cloud-firestorereact-custom-hooks

Return function and useState from customhook


I have a file uploader for firebase and it works wonderfully, except for the last thing. I have the function inside a custom hook and when applied it works, however I would like to return the status of progress ( either complete or error ) yet the only way I can seem to pass back the useState is by using a useEffect, which then causes other issues.

I have the custom hook operate with an onClick, to track the status I am using a useState which gets changed depending on the outcome.

However I can't return the function and the useState..

import { ref, uploadBytesResumable } from "firebase/storage"
import { proStorage } from "../firebase/config"
import { v4 } from "uuid"
import { useState } from "react"

const useUploader = (data, foldername) => {
  const [upLoadcomplete, setuploacomplete] = useState()
  const uploadFiles = async () => {
    for (let i = 0; i < data.length; i++) {
      const name = `$${v4()}`
      const location = `${foldername}/${name}`
      const metadata = {
        customMetadata: {
          uuid_name: name,
        },
      }
      const dataRef = ref(proStorage, location)
      const uploadtask = uploadBytesResumable(dataRef, data[i], metadata)
      console.log(uploadtask.metadata)

      uploadtask.on(
        "state_changed",
        (snapshot) => {
          const progress =
            (snapshot.bytesTransferred / snapshot.totalBytes) * 100
          console.log("Upload is " + progress + "% done")
          // eslint-disable-next-line
          switch (snapshot.state) {
            case "paused":
              console.log("Upload is paused")
              break
            case "running":
              console.log("Upload is running")
              break
          }
        },
        (error) => {
          setuploacomplete("Error with upload try again")
        }
      )
    }
    setuploacomplete("Upload is now complete")
  }

  return uploadFiles
}
export default useUploader

I was following this for awhile but I am doing multipule files and the video is abit outdated with the newer ways of doing things.

I am hoping for some help!


Solution

  • You can use an object in your custom hook to return the method and the useState.

    Example:

    import...
    
    const useUploader = (data, foldername) => {
      const [upLoadcomplete, setuploacomplete] = useState()
    
      const uploadFiles = async () => {
        // ...
      }
    
      return {
        uploadFiles,
        upLoadcomplete,
      }
    }
    

    Then, you can use the custom hook like this:

    const { uploadFiles, upLoadcomplete } = useUploader(data, foldername)
    
    // Upload the files
    uploadFiles()
    
    // Check the status of the upload
    if (upLoadcomplete === "Upload is now complete") {
      // ...
    } else if (upLoadcomplete === "Error with upload try again") {
      // ...
    }
    

    This approach provides the following benefits: