How do I connect Firebase Storage with Cloud Firestore so my images are associated to their respective posts?

Viewed 1953

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.com/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 '../components/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;
1 Answers

It is actually pretty simple, to achieve this follow steps below:

  1. 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.com/docs/storage/web/download-files

  1. 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.

  2. Now you can show images using this download url in your page using busboy library

https://www.npmjs.com/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

Related