I'm having a hard time putting the file in firebase so I can retrieve its getDownloadURL
.
Here's what I got
import React, {useState, useEffect} from 'react'
import { Container, Button, Row, Col, Form, Alert } from 'react-bootstrap'
import PageHeader from '../components/PageHeader'
import { projectFirestore, projectStorage } from '../firebase/config'
const Dashboard = () => {
const [ error, setError] = useState('')
const [ name, setName ] = useState("")
const [ link, setLink ] = useState("")
const [ file, setFile ] = useState(null)
const [ desc, setDesc ] = useState("")
const [ projects, setProjects ] = useState([])
const [ url, setUrl ] = useState("")
const [ message, setMessage ] = useState("")
useEffect(() => {
projectFirestore.collection('projects').onSnapshot((snapshot) =>{
const tempProject = []
snapshot.forEach(doc => {
tempProject.push({...doc.data(), id: doc.id});
})
setProjects(tempProject)
})
}, [])
const onNameChange = (e) => { setName(e.target.value) }
const onLinkChange = (e) => { setLink(e.target.value) }
const onDescChange = (e) => { setDesc(e.target.value) }
const handleSubmit = async (e) => {
e.preventDefault()
try {
setMessage('')
setError('')
if(!name){
return
}
const storageRef = projectStorage.ref()
const fileRef = storageRef.child(file.name)
await fileRef.put(file)
setUrl(fileRef.getDownloadURL())
projectFirestore.collection('projects')
.doc( name, link, url, desc )
.set({ name, link, url, desc })
setMessage('Project added succesfully')
setName('')
setLink('')
setFile(null)
setDesc('')
} catch {
setError('Project fail to add')
}
}
return (
<div className="">
<Container>
<PageHeader title="Dashboard" />
<Row>
<Col xs={12}>
<h4>Add Project</h4>
{message && <Alert variant="success">{message}</Alert> }
{error && <Alert variant="danger">{error}</Alert> }
<Form onSubmit={handleSubmit}>
<Row>
<Col xs={12} lg={8}>
<Form.Group className="mb-3">
<Form.Label>Name</Form.Label>
<Form.Control
type="text"
value={name}
onChange={onNameChange}/>
</Form.Group>
<Form.Group className="mb-3">
<Form.Label>Description</Form.Label>
<Form.Control
as="textarea"
rows={5}
value={desc}
onChange={onDescChange}/>
</Form.Group>
<Form.Group className="mb-3">
<Form.Label>Link</Form.Label>
<Form.Control
type="text"
value={link}
onChange={onLinkChange} />
</Form.Group>
</Col>
<Col xs={12} lg={4}>
<Form.Group className="mb-3">
<Form.Label>Image</Form.Label>
<Form.Control type="file" onChange={(e) => setFile(e.target.files[0])}/>
</Form.Group>
<div>
{projects.map(project => (
<div key={project.id} to={`/${project.id}`}>
<img src={project.url} alt={project.name} />
<h5>{project.name}</h5>
</div>
))}
</div>
</Col>
</Row>
<div className="d-flex justify-content-end">
<Button variant="primary" type="submit"> Send</Button>
</div>
</Form>
</Col>
</Row>
</Container>
</div>
)
}
export default Dashboard
CodePudding user response:
The code looks fine but I would add some validation and check if a file is actually selected by user. The doc()
method takes a string as documentID. Also getDownloadURL()
returns a promise. Try refactoring the code to:
const handleSubmit = async (e) => {
e.preventDefault()
try {
setMessage('')
setError('')
if(!name){
return
}
if (!file) {
console.log("No file selected")
return
}
console.log("Starting file upload")
const storageRef = projectStorage.ref()
const fileRef = storageRef.child(file.name)
await fileRef.put(file)
console.log("File uploaded")
const fileUrl = await fileRef.getDownloadURL()
console.log(fileUrl)
setUrl(fileUrl)
await projectFirestore.collection('projects')
.doc("some_document_id")
.set({ name, link, url: fileUrl, desc })
setMessage('Project added succesfully')
setName('')
setLink('')
setFile(null)
setDesc('')
} catch {
setError('Project fail to add')
}
}