React.js Firebase Tutorial: Building Firestore CRUD Web Application

by Didin J. on Oct 15, 2018 React.js Firebase Tutorial: Building Firestore CRUD Web Application

The comprehensive step by step tutorial on building Firestore Database CRUD Web Application using React.js and Google Firebase

The comprehensive step by step tutorial on building Firestore Database CRUD Web Application using React.js and Google Firebase. Previously, we have created a tutorial of Firebase Firestore Database using React Native. Now, we have created the same tutorial for React.js but this time we implement to the Web Application. You will learn how to use Firebase Firestore Database with React.js Web Application. We cover the common CRUD (Create, Read, Update, Delete) operation of Firebase Firestore Database.


Shortcut to the steps:


The flow for this React Firebase application is very simple. Just, show the list of data, add, edit, delete and show the data details. They all done easily using the Firebase module. The Firebase configuration will be the same way as another tutorial about Firebase on our website.

React Firebase - Firebase Module

Using React Firebase with standard Firebase library similar with another Front-end frameworks

  • Node.js (Recommended version)
  • React.js
  • Firebase
  • Terminal (Mac/Linux) or Node Command Line (Windows)
  • IDE or Text Editor

We assume that you have already installed Node.js. Make sure Node.js command line is working (on Windows) or runnable in Linux/OS X terminal.


Setup Firebase Firestore Database

Setup Google Firebase is very simple. Open your browser then go to Google Firebase Console and log in using your Google account.

React.js Firebase Tutorial: Building Firestore CRUD Web Application - Firebase Console

Click the `Add Project` button, name it as you like (ours: Djamware) and checks all checkboxes. Finally, click `Create Project` button then wait a few seconds and click the `Continue` button. You will be redirected to this page.

React.js Firebase Tutorial: Building Firestore CRUD Web Application - Project Overview

Go to Develop menu on the left menu then click `Create Database` on Cloud Firestore page.

React.js Firebase Tutorial: Building Firestore CRUD Web Application - Security Rules

Choose `Start in test mode` then click `Enabled` button.

React.js Firebase Tutorial: Building Firestore CRUD Web Application - Add Collection

Click `Add Collection` button to add the new collection for this tutorial. Fill collection ID (ours: 'boards') then click next. Add the required fields then click finish the wizard.

React.js Firebase Tutorial: Building Firestore CRUD Web Application - Collection Items

Now, the Firebase Firestore Database is ready to access. Make sure that your iOS and Android app match with the configuration files (json/plist). You can get the configuration parameters in the Authentication side menu then you will see the Web Setup button on the top right of the screen.


Install and Create React App

Open the terminal or Node.js command line then go to your React.js projects folder. We will install React.js app creator for creating a React.js app easily. For that, type this create-react-app command.

sudo npm install -g create-react-app

Now, create a React app by type this command.

create-react-app react-firestore

This command will create a new React app with the name `react-firestore` and this process can take minutes because all dependencies and modules also installing automatically. Next, go to the newly created app folder.

cd ./react-firestore

Now, run the React app for the first time using this command.

npm start

It will automatically open the default browser the point to `http://localhost:3000`, so the landing page should be like this.

React.js Firebase Tutorial: Building Firestore CRUD Web Application - React.js App


Install and Configure the Firebase Module

We use Firebase module to access the Firebase Firestore Database. The Firebase module is available as an NPM module. For that, type this command to install the module.

npm install --save firebase

Next, create a new file `Firebase.js` in the root of the project folder for Firebase configuration.

touch src/Firebase.js

Open and edit `src/Firebase.js` then replace all codes with this.

import * as firebase from 'firebase';
import firestore from 'firebase/firestore'

const settings = {timestampsInSnapshots: true};

const config = {
  apiKey: "YOUR_API_KEY",
  authDomain: "YOUR_AUTH_DOMAIN",
  databaseURL: "YOUR_DATABASE_URL",
  projectId: "YOUR_PROJECT_ID",
  storageBucket: "YOUR_STORAGE_BUCKET",
  messagingSenderId: "YOUR_MESSAGING_ID"
};
firebase.initializeApp(config);

firebase.firestore().settings(settings);

export default firebase;

You can find or get those configuration parameters by click on Web Setup button in the page authentication of Firebase Console.


Add React Router DOM

Before creating React Router DOM, first, we have to install the required NPM modules including react-router-dom and bootstrap by typing these commands.

npm install --save react-router-dom
npm install --save-dev bootstrap

The React.js CRUD web application required pages to creating, show details and edit Board data. For that, type this commands to create those components.

mkdir src/components
touch src/components/Create.js
touch src/components/Show.js
touch src/components/Edit.js

Next, we will create routes for those components. Open and edit `src/index.js` then replace all codes with this.

import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router, Route } from 'react-router-dom';
import '../node_modules/bootstrap/dist/css/bootstrap.min.css';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import Edit from './components/Edit';
import Create from './components/Create';
import Show from './components/Show';

ReactDOM.render(
  <Router>
      <div>
        <Route exact path='/' component={App} />
        <Route path='/edit/:id' component={Edit} />
        <Route path='/create' component={Create} />
        <Route path='/show/:id' component={Show} />
      </div>
  </Router>,
  document.getElementById('root')
);

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: http://bit.ly/CRA-PWA
serviceWorker.unregister();

As you see that Edit, Create and Show added as the separate component. Bootstrap also included in the import to make the views better.


Create List of Boards

To show the list of the board in the Board components, open and edit `src/App.js` then replace all codes with these codes that contain get data from Firebase and display using to React.js template with Bootstrap for styling.

import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import './App.css';
import firebase from './Firebase';

class App extends Component {
  constructor(props) {
    super(props);
    this.ref = firebase.firestore().collection('boards');
    this.unsubscribe = null;
    this.state = {
      boards: []
    };
  }

  onCollectionUpdate = (querySnapshot) => {
    const boards = [];
    querySnapshot.forEach((doc) => {
      const { title, description, author } = doc.data();
      boards.push({
        key: doc.id,
        doc, // DocumentSnapshot
        title,
        description,
        author,
      });
    });
    this.setState({
      boards
   });
  }

  componentDidMount() {
    this.unsubscribe = this.ref.onSnapshot(this.onCollectionUpdate);
  }

  render() {
    return (
      <div class="container">
        <div class="panel panel-default">
          <div class="panel-heading">
            <h3 class="panel-title">
              BOARD LIST
            </h3>
          </div>
          <div class="panel-body">
            <h4><Link to="/create">Add Board</Link></h4>
            <table class="table table-stripe">
              <thead>
                <tr>
                  <th>Title</th>
                  <th>Description</th>
                  <th>Author</th>
                </tr>
              </thead>
              <tbody>
                {this.state.boards.map(board =>
                  <tr>
                    <td><Link to={`/show/${board.key}`}>{board.title}</Link></td>
                    <td>{board.description}</td>
                    <td>{board.author}</td>
                  </tr>
                )}
              </tbody>
            </table>
          </div>
        </div>
      </div>
    );
  }
}

export default App;


Create Show Details and Delete Board

To show board details that listed on the home page, open and edit `src/components/Show.js` then add these lines of codes contain get data by key or ID from Firebase then display to React.js template with Bootstrap as the style.

import React, { Component } from 'react';
import firebase from '../Firebase';
import { Link } from 'react-router-dom';

class Show extends Component {

  constructor(props) {
    super(props);
    this.state = {
      board: {},
      key: ''
    };
  }

  componentDidMount() {
    const ref = firebase.firestore().collection('boards').doc(this.props.match.params.id);
    ref.get().then((doc) => {
      if (doc.exists) {
        this.setState({
          board: doc.data(),
          key: doc.id,
          isLoading: false
        });
      } else {
        console.log("No such document!");
      }
    });
  }

  delete(id){
    firebase.firestore().collection('boards').doc(id).delete().then(() => {
      console.log("Document successfully deleted!");
      this.props.history.push("/")
    }).catch((error) => {
      console.error("Error removing document: ", error);
    });
  }

  render() {
    return (
      <div class="container">
        <div class="panel panel-default">
          <div class="panel-heading">
          <h4><Link to="/">Board List</Link></h4>
            <h3 class="panel-title">
              {this.state.board.title}
            </h3>
          </div>
          <div class="panel-body">
            <dl>
              <dt>Description:</dt>
              <dd>{this.state.board.description}</dd>
              <dt>Author:</dt>
              <dd>{this.state.board.author}</dd>
            </dl>
            <Link to={`/edit/${this.state.key}`} class="btn btn-success">Edit</Link>&nbsp;
            <button onClick={this.delete.bind(this, this.state.key)} class="btn btn-danger">Delete</button>
          </div>
        </div>
      </div>
    );
  }
}

export default Show;


Create Add Board

For adding a new board, open and edit `src/components/Create.js` then replace all codes with these codes.

import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import firebase from '../Firebase';
import { Link } from 'react-router-dom';

class Create extends Component {

  constructor() {
    super();
    this.ref = firebase.firestore().collection('boards');
    this.state = {
      title: '',
      description: '',
      author: ''
    };
  }
  onChange = (e) => {
    const state = this.state
    state[e.target.name] = e.target.value;
    this.setState(state);
  }

  onSubmit = (e) => {
    e.preventDefault();

    const { title, description, author } = this.state;

    this.ref.add({
      title,
      description,
      author
    }).then((docRef) => {
      this.setState({
        title: '',
        description: '',
        author: ''
      });
      this.props.history.push("/")
    })
    .catch((error) => {
      console.error("Error adding document: ", error);
    });
  }

  render() {
    const { title, description, author } = this.state;
    return (
      <div class="container">
        <div class="panel panel-default">
          <div class="panel-heading">
            <h3 class="panel-title">
              ADD BOARD
            </h3>
          </div>
          <div class="panel-body">
            <h4><Link to="/" class="btn btn-primary">Book List</Link></h4>
            <form onSubmit={this.onSubmit}>
              <div class="form-group">
                <label for="title">Title:</label>
                <input type="text" class="form-control" name="title" value={title} onChange={this.onChange} placeholder="Title" />
              </div>
              <div class="form-group">
                <label for="description">Description:</label>
                <textArea class="form-control" name="description" onChange={this.onChange} placeholder="Description" cols="80" rows="3">{description}</textArea>
              </div>
              <div class="form-group">
                <label for="author">Author:</label>
                <input type="text" class="form-control" name="author" value={author} onChange={this.onChange} placeholder="Author" />
              </div>
              <button type="submit" class="btn btn-success">Submit</button>
            </form>
          </div>
        </div>
      </div>
    );
  }
}

export default Create;


Create Edit Board

To edit board, open and edit, `src/components/Edit.js` then add these lines of codes.

import React, { Component } from 'react';
import firebase from '../Firebase';
import { Link } from 'react-router-dom';

class Edit extends Component {

  constructor(props) {
    super(props);
    this.state = {
      key: '',
      title: '',
      description: '',
      author: ''
    };
  }

  componentDidMount() {
    const ref = firebase.firestore().collection('boards').doc(this.props.match.params.id);
    ref.get().then((doc) => {
      if (doc.exists) {
        const board = doc.data();
        this.setState({
          key: doc.id,
          title: board.title,
          description: board.description,
          author: board.author
        });
      } else {
        console.log("No such document!");
      }
    });
  }

  onChange = (e) => {
    const state = this.state
    state[e.target.name] = e.target.value;
    this.setState({board:state});
  }

  onSubmit = (e) => {
    e.preventDefault();

    const { title, description, author } = this.state;

    const updateRef = firebase.firestore().collection('boards').doc(this.state.key);
    updateRef.set({
      title,
      description,
      author
    }).then((docRef) => {
      this.setState({
        key: '',
        title: '',
        description: '',
        author: ''
      });
      this.props.history.push("/show/"+this.props.match.params.id)
    })
    .catch((error) => {
      console.error("Error adding document: ", error);
    });
  }

  render() {
    return (
      <div class="container">
        <div class="panel panel-default">
          <div class="panel-heading">
            <h3 class="panel-title">
              EDIT BOARD
            </h3>
          </div>
          <div class="panel-body">
            <h4><Link to={`/show/${this.state.key}`} class="btn btn-primary">Board List</Link></h4>
            <form onSubmit={this.onSubmit}>
              <div class="form-group">
                <label for="title">Title:</label>
                <input type="text" class="form-control" name="title" value={this.state.title} onChange={this.onChange} placeholder="Title" />
              </div>
              <div class="form-group">
                <label for="description">Description:</label>
                <input type="text" class="form-control" name="description" value={this.state.description} onChange={this.onChange} placeholder="Description" />
              </div>
              <div class="form-group">
                <label for="author">Author:</label>
                <input type="text" class="form-control" name="author" value={this.state.author} onChange={this.onChange} placeholder="Author" />
              </div>
              <button type="submit" class="btn btn-success">Submit</button>
            </form>
          </div>
        </div>
      </div>
    );
  }
}

export default Edit;


Run and Test The React.js and Firebase Web Application

Now, we can test our completed app by type this command.

npm start

On the browser go to `localhost:3000` then you will see this home page.

React.js Firebase Tutorial: Building Firestore CRUD Web Application - Board List
React.js Firebase Tutorial: Building Firestore CRUD Web Application - Board Details
React.js Firebase Tutorial: Building Firestore CRUD Web Application - Edit Board
React.js Firebase Tutorial: Building Firestore CRUD Web Application - Add oard

That it's, the React.js Firebase Tutorial: Building Firestore CRUD Web Application. You can find the full working source code from our GitHub.

That just the basic. If you need more deep learning about MERN Stack, React.js or React Native you can take the following cheap course:

Thanks!