Reputation: 13
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
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