0

To preface, I am just beginning to dive into React.js, so solution might be simple.

I am using React.js with firebase and react-router for a basic multipage site with a form that posts text. On the TicketList page, I am attempting to do a data post to Firebase, which works, but when I go to another page and come back to the TicketList page, I get the error: TypeError: Cannot read property 'database' of undefined.

From the tutorial I am following, the code is the same, except all my TicketList code is on the App.js, since the tutorial didn't have react-router. Not sure if this structure has to do with this issue. The tutorial also doesn't have the this.app = firebase.initializeApp(DB_CONFIG); inside if (!firebase.apps.length), but without that bit I get the error: Firebase App named '[DEFAULT]' already exists.

If I put this.database = this.app.database().ref().child('tickets'); inside the if (!firebase.apps.length) I get the error: TypeError: Cannot read property 'on' of undefined, but now I think I am straying too far from the original problem, and I think my understanding is off. Anyone have some direction for me? Thanks!

Structure:

src 
    > components 
    > config
      > config.js
    > routes
      > About.js
      > TicketList.js
      > index.js
    > App.js

TicketList.js :

import React, { Component } from 'react';
import Ticket from '../components/Ticket.js'
import TicketForm from '../components/TicketForm.js'
import { DB_CONFIG } from '../config/config.js';
import firebase from 'firebase/app';
import 'firebase/database';

// CSS
import '../assets/css/TicketList.css';
import '../assets/css/App.css';

class TicketList extends Component {
  constructor(props){
    super(props);
    this.addTicket = this.addTicket.bind(this);
    this.removeTicket = this.removeTicket.bind(this);
    if (!firebase.apps.length) {
      this.app = firebase.initializeApp(DB_CONFIG);
      this.database = this.app.database().ref().child('tickets');
    }

    // We're going to setup the React state of our component
    this.state = {
      tickets: [],
    }
  }

  componentWillMount(){
    const previousTickets = this.state.tickets;

    // DataSnapshot
    this.database.on('child_added', snap => {
      previousTickets.push({
        id: snap.key,
        ticketContent: snap.val().ticketContent,
      })

      this.setState({
        tickets: previousTickets
      })
    })

    this.database.on('child_removed', snap => {
      for(var i=0; i<previousTickets.length; i++){
        if(previousTickets[i].id === snap.key){
          previousTickets.splice(i, 1);
        }
      }

      this.setState({
        tickets: previousTickets
      })
    })
  }

  addTicket(ticket){
    this.database.push().set({ ticketContent: ticket });
  }

  removeTicket(ticketId){
    this.database.child(ticketId).remove();
  }

  render() {
    return (
      <div>
        <div className="m-container">
          <h1>Open Questions</h1>
          <hr/>
        </div>
        <div>
        {
          this.state.tickets.map((ticket) => {
              return (
                <Ticket 
                ticketContent={ticket.ticketContent} 
                ticketId={ticket.id} 
                key={ticket.id} 
                removeTicket={this.removeTicket} />
              )
          })
        }

        </div>
        <div>
          <TicketForm addTicket={this.addTicket} />
        </div>
      </div>
    );
  }
}

export default TicketList;

1 Answer 1

1

The problem is here:

this.app = firebase.initializeApp(DB_CONFIG);
this.database = this.app.database().ref().child('tickets');

firebase.initialize is asynchronous, which is why this.app is undefined by the time you reference it.

instead, try:

firebase.initializeApp(DB_CONFIG);
this.database = firebase.database().ref().child('tickets');
Sign up to request clarification or add additional context in comments.

2 Comments

Awesome, makes sense, solved, but still needed firebase.initializeApp(DB_CONFIG); inside if (!firebase.apps.length)
Mind if I ask why if (!firebase.apps.length) was needed there? Wondering if I should be checking whether an app has been initialised everytime

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.