jimjim32
jimjim32

Reputation: 13

Upload to firebase storage. My app is uploading the file twice when clicking on a form submit button

So here is my problem. i am trying to uplaod a file to firebase storage but everytime i click on the upload, for some reasons, the file is uploaded twice. I am using react and i created a custom hook to handle the upload to firebase. I am using react-bootstrap to have a form to get the data i need to send. There are a photo file, an input text and a select. Here is my custom hook:

const UseStorage = (file) => {
const [progress, setProgress] = useState(0);
const [error, setError] = useState(null);
const [url, setUrl] = useState(null);


useEffect(() => {
    const storageRef = ref(storage, `images/${Date.now()}-${file.name}`);
    const uploadTask = uploadBytesResumable(storageRef, file);
    uploadTask.on('state_changed', 
        (snapshot) => {
            const percentage = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
            setProgress(percentage);
        }, 
        (error) => {
        setError(error);
        }, 
        async () => {
        const url =  await getDownloadURL(uploadTask.snapshot.ref);

            //console.log('File available at', url);
            setUrl(url);
        });
}, [file]);
return {progress, error, url }
}
export default UseStorage;

Here is my component which handle the data :

export default function AddItem( {showModal, handleClose} ) {
// data to send to firebase
const [data, setData] = useState(null);
//ref of the modal input
const refName = useRef();
const refFile = useRef();
const refCategory = useRef();
// error state
const [errorFile, setErrorFile ] = useState(null)
const types = ['image/png', 'image/jpeg'];

const handleSubmit = (e) => {
    e.preventDefault();
    if (refName.current.value === ''){
        setData(null);
        setErrorFile("Name can't be empty");
        return;
    }
    if (refCategory.current.value === '') {
        setData(null);
        setErrorFile("Category can't be empty");
        return;
    }

    let selectedFile = refFile.current.files[0];
    if (selectedFile && types.includes(selectedFile.type) ){
        setData({
            file:selectedFile,
            name: refName.current.value,
            category: refCategory.current.value
        });
        setErrorFile('');
    }
    else {
        setData(null);
        setErrorFile('Please select an image file (png or jpeg).')

    }
};
 return (
  <>
  <Modal show={showModal} onHide={handleClose} backdrop="static">
    <Modal.Header closeButton>
      <Modal.Title>Add Item</Modal.Title>
    </Modal.Header>
    <Modal.Body>
      <Form onSubmit={handleSubmit}>
        <Form.Group className="mb-3" controlId="exampleForm.ControlInput1">
          <Form.Label>Name</Form.Label>
          <Form.Control
          type="text"
          required
          ref={refName}
          />
        </Form.Group>
        <Form.Group controlId="formFile" className="mb-3">
          <Form.Label>Photo</Form.Label>
          <Form.Control type="file" ref={refFile}/>
        </Form.Group>
        <Form.Label>Category</Form.Label>
        <Form.Select aria-label="Default select example" ref={refCategory}>
          <option value="Saiyajin">Saiyajin</option>
          <option value="Namek">Namek</option>
          <option value="Ennemy">Ennemy</option>
          <option value="Cyborg">Cyborg</option>
        </Form.Select>
        <Button className="mt-3" variant="primary" type="submit">
          Add
        </Button>
      </Form>
    </Modal.Body>
    {errorFile && <Alert variant="danger">{errorFile} </Alert>}
   <Modal.Footer>
    <Button variant="secondary" onClick={handleClose}>
      Cancel
    </Button>
  </Modal.Footer>
    {data && <ProgressBarCustom data={data} setData={setData} /> }
  </Modal>
  </>
 )
 }

And here is my customProgressBar component which use the custom hook:

const  ProgressBarCustom = ( {data, setData} ) => {
const { progress, url } = UseStorage(data.file);
useEffect(() => {
    if(url){
        setData(null);
    }
},[url, setData]);

console.log(progress, url)
return (
    <ProgressBar now={progress} />
)
}

export default ProgressBarCustom;

For whatever reasons, my file end up uploaded twice on storage with 2 different name ( as i use Date.now() to create the storage ref). I have tried using ref and also state and i end up with the same behaviour, but if i move all the custom hook upload process directly in my component handleSubmit() method, the upload is fine and i only upload it one time as desired. Does someone have an idea on what i am doing wrong ? Thanks

Upvotes: 0

Views: 428

Answers (1)

Kavikumar M
Kavikumar M

Reputation: 11

Try to remove React.StrictMode from index.js:

Index.js( before removing):

import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <React.StrictMode>
     <App />
  </React.StrictMode>
);

Index.js( after removing):

import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
     <App />
);

Hope this helps you!

Upvotes: 1

Related Questions