skip to Main Content

I have been trying to solve this for awhile and have reduced it to the barest minium I can, I have this page

import React, { useState } from "react"
import useUploader from "./uploaderexample"

function Uploadpage() {
  // Handles file selection
  const changeHandler = (e) => {
    setFiles(e.target.files)
  }

  // set use state for file selction
  const [files, setFiles] = useState()
  const [foldername, setFoldername] = useState("")

  return (
    <div>
      <input type="file" onChange={changeHandler} />
      <input type="text" onSubmit={setFoldername} placeholder="folder name" />
      <button
        className="bg-black text-white"
        onClick={() => useUploader(files, foldername)}
      >
        click here to upload
      </button>
      <div>
        return the status of upload here, this where I would like the status to
        be loaded from the useUploader function
      // this is a placeholder for conditional div
      <div>Successful upload</div>
      </div>
    </div>
  )
}
export default Uploadpage

A very simple page that allowes you to select files, name a folder and then upload it.

The useUploader looks like this:

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

// incoming data and name of folder to put them in for upload
const useUploader = (data, foldername) => {

  // set use state of outcome as a string
  const [upLoadcomplete, setuploacomplete] = useState("")

  //files and create folder on firebase
  const uploadFiles = async () => {
    // loop files
    for (let i = 0; i < data.length; i++) {
      //set folder
      const location = `${foldername}/filename`
      const dataRef = ref(proStorage, location)
      //upload 
      uploadBytesResumable(dataRef, data[i])
      // to keep simple imagine it works
      setuploacomplete['Success']

    }
  }

  // return the function and the outcome of the upload
  return [uploadFiles, upLoadcomplete]
}
export default useUploader

I have tried everything I can think og, however I am unable to fingure out how to make this work, I can return the uploadFiles function with no issues. However, when I try to return the upLoadcomplete, it causes an error

error when returning both

The only way I know how to fix this would be to not return the status, which is the opposite of what I am trying to do.

My flow would look like this:
Ideal flow

Essentially my issue is that I can’t return the function and also the string…(both are on seperate Jsx’s)

Any help?

2

Answers


  1. If the return value of useUploader is an array:

    return [uploadFiles, upLoadcomplete]
    

    You can’t use useUploader as a function directly:

    <button
      className="bg-black text-white"
      onClick={() => useUploader(files, foldername)}
    >
    

    Instead destructure the return value of useUploader, and use uploadFiles in the onClick:

    function Uploadpage() {
      ...
    
      // set use state for file selction
      const [files, setFiles] = useState()
      const [foldername, setFoldername] = useState("")
      const [uploadFiles, upLoadcomplete] = useUploader(files, foldername) // desturcture the return value
    
      // call uploadFiles in the onClick
      return (
        ...
        <button
          className="bg-black text-white"
          onClick={() => uploadFiles()}
        >
        ...
      )
    }
    
    Login or Signup to reply.
  2. You cannot call hook functions inside another function in react. the hooks MUST be called in the root of the component and MUST be called on every render.

    so here is what you have to do:

    import React, { useState } from "react"
    import useUploader from "./uploaderexample"
    
    function Uploadpage() {
      // Handles file selection
      const changeHandler = (e) => {
        setFiles(e.target.files)
      }
    
      // set use state for file selction
      const [files, setFiles] = useState()
      const [foldername, setFoldername] = useState("")
    
      const [uploadFiles, upLoadcomplete] = useUploader(files, foldername)
    
      return (
        <div>
          <input type="file" onChange={changeHandler} />
          <input type="text" onSubmit={setFoldername} placeholder="folder name" />
          <button
            className="bg-black text-white"
            onClick={() => uploadFiles()} 
          >
            click here to upload
          </button>
          <div>
            return the status of upload here, this where I would like the status to
            be loaded from the useUploader function
          // this is a placeholder for conditional div
          <div>Successful upload</div>
          </div>
        </div>
      )
    }
    export default Uploadpage
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search