I have a CRUD React app where you can create articles. There is a 'title', 'content' and 'image'.
I have a collection in Cloud Firestore called 'articles'. The documents have the fields: 'title' and 'content' so every time I create an article in my react app, a new document is created.
The next step was to be able to add images to the articles.
I managed to connect to Firebase and upload an image to Firebase Storage from my React page. However how do I connect the images to their articles? Like, how do I make the connection between Cloud Firestore and Storage?
Do I create an extra field in my documents called 'images'? But then how do I reference it? I also want to try and avoid duplicates.
UploadImage.js
import React, { useState, Component } from "react";
import { storage } from "../Firebase";
function UploadFile() {
const [image, setImage] = useState(null);
const [url, setUrl] = useState("");
const [progress, setProgress] = useState(0);
const handleChange = e => {
if (e.target.files[0]) {
setImage(e.target.files[0]);
}
};
const handleUpload = () => {
const uploadTask = storage.ref(`images/${image.name}`).put(image);
uploadTask.on(
"state_changed",
snapshot => {
const progress = Math.round(
(snapshot.bytesTransferred / snapshot.totalBytes) * 100
);
setProgress(progress);
},
error => {
console.log(error);
},
() => {
storage
.ref("images")
.child(image.name)
.getDownloadURL()
.then(url => {
setUrl(url);
});
}
);
};
console.log("image: ", image);
return (
<div>
<progress value={progress} max="100" />
<br />
<br />
<input type="file" onChange={handleChange} />
<button onClick={handleUpload}>Upload</button>
<br />
{url}
<br />
<img src={url || ";} alt="firebase-image" />
</div>
);
}
export default UploadFile;
This is my 'Add Article' form-->
AddArticle.js
import React, { Component } from 'react';
import firebase from '../Firebase';
import UploadFile from '../ponents/UploadFile';
class AddArticle extends Component {
constructor() {
super();
this.ref = firebase.firestore().collection('articles');
this.state = {
title: '',
content: ''
};
}
onChange = (e) => {
const state = this.state
state[e.target.name] = e.target.value;
this.setState(state);
}
onSubmit = (e) => {
e.preventDefault();
const { title, content } = this.state;
this.ref.add({
title,
content
}).then((docRef) => {
this.setState({
title: '',
content: ''
});
this.props.history.push("/")
})
.catch((error) => {
console.error("Error adding document: ", error);
});
}
render() {
const { title, content } = this.state;
return (
<div className="container">
<br></br><br></br><br></br>
<div className="panel panel-default">
<div className="panel-heading">
<h3 className="panel-title text-center">
Create a new article
</h3>
</div>
<br></br><br></br>
<div className="panel-body">
<form onSubmit={this.onSubmit}>
<div className="form-group">
<label for="title">Title:</label>
<input type="text" className="form-control" name="title" value={title} onChange={this.onChange} placeholder="Title" />
</div>
<div className="form-group">
<label for="content">Content:</label>
<textArea className="form-control" name="content" onChange={this.onChange} placeholder="Content" cols="80" rows="20">{content}</textArea>
</div>
<UploadFile />
<button type="submit" className="btn btn-success">Submit</button>
</form>
</div>
</div>
</div>
);
}
}
export default AddArticle;
I have a CRUD React app where you can create articles. There is a 'title', 'content' and 'image'.
I have a collection in Cloud Firestore called 'articles'. The documents have the fields: 'title' and 'content' so every time I create an article in my react app, a new document is created.
The next step was to be able to add images to the articles.
I managed to connect to Firebase and upload an image to Firebase Storage from my React page. However how do I connect the images to their articles? Like, how do I make the connection between Cloud Firestore and Storage?
Do I create an extra field in my documents called 'images'? But then how do I reference it? I also want to try and avoid duplicates.
UploadImage.js
import React, { useState, Component } from "react";
import { storage } from "../Firebase";
function UploadFile() {
const [image, setImage] = useState(null);
const [url, setUrl] = useState("");
const [progress, setProgress] = useState(0);
const handleChange = e => {
if (e.target.files[0]) {
setImage(e.target.files[0]);
}
};
const handleUpload = () => {
const uploadTask = storage.ref(`images/${image.name}`).put(image);
uploadTask.on(
"state_changed",
snapshot => {
const progress = Math.round(
(snapshot.bytesTransferred / snapshot.totalBytes) * 100
);
setProgress(progress);
},
error => {
console.log(error);
},
() => {
storage
.ref("images")
.child(image.name)
.getDownloadURL()
.then(url => {
setUrl(url);
});
}
);
};
console.log("image: ", image);
return (
<div>
<progress value={progress} max="100" />
<br />
<br />
<input type="file" onChange={handleChange} />
<button onClick={handleUpload}>Upload</button>
<br />
{url}
<br />
<img src={url || "http://via.placeholder./300"} alt="firebase-image" />
</div>
);
}
export default UploadFile;
This is my 'Add Article' form-->
AddArticle.js
import React, { Component } from 'react';
import firebase from '../Firebase';
import UploadFile from '../ponents/UploadFile';
class AddArticle extends Component {
constructor() {
super();
this.ref = firebase.firestore().collection('articles');
this.state = {
title: '',
content: ''
};
}
onChange = (e) => {
const state = this.state
state[e.target.name] = e.target.value;
this.setState(state);
}
onSubmit = (e) => {
e.preventDefault();
const { title, content } = this.state;
this.ref.add({
title,
content
}).then((docRef) => {
this.setState({
title: '',
content: ''
});
this.props.history.push("/")
})
.catch((error) => {
console.error("Error adding document: ", error);
});
}
render() {
const { title, content } = this.state;
return (
<div className="container">
<br></br><br></br><br></br>
<div className="panel panel-default">
<div className="panel-heading">
<h3 className="panel-title text-center">
Create a new article
</h3>
</div>
<br></br><br></br>
<div className="panel-body">
<form onSubmit={this.onSubmit}>
<div className="form-group">
<label for="title">Title:</label>
<input type="text" className="form-control" name="title" value={title} onChange={this.onChange} placeholder="Title" />
</div>
<div className="form-group">
<label for="content">Content:</label>
<textArea className="form-control" name="content" onChange={this.onChange} placeholder="Content" cols="80" rows="20">{content}</textArea>
</div>
<UploadFile />
<button type="submit" className="btn btn-success">Submit</button>
</form>
</div>
</div>
</div>
);
}
}
export default AddArticle;
Share
Improve this question
edited Aug 13, 2020 at 18:40
Doug Stevenson
319k36 gold badges456 silver badges473 bronze badges
asked Aug 13, 2020 at 18:28
cldevcldev
7819 silver badges19 bronze badges
0
1 Answer
Reset to default 5It is actually pretty simple, to achieve this follow steps below:
- After uploading your image to firebase storage you should get download url for that particular image (I linked firebase documentation link below on how to achieve that).
https://firebase.google./docs/storage/web/download-files
If you successfully fetched download url from firebase storage now it is time to create separate field under your document named such as "postImageUrl" (you can name whatever you want) and save download url under this field.
Now you can show images using this download url in your page using busboy library
https://www.npmjs./package/busboy
Note: I am an Android Developer so I tried my best to help. If you have further questions don't hesitate to ask