Skip to content
Advertisement

TypeError: Cannot read property ‘on’ of undefined – App.componentWillMount

I am making an app in javascript with firebase. The problem is with the property “on”. I cant seem to fix it. The problem in line 31. –>> this.database.on(‘child_added’, snap => { The error is –>> TypeError: Cannot read property ‘on’ of undefined. Any help is appreciated! Explanation would be nice too.

import React, { Component } from 'react';
import './App.css';
import Card from './Card/Card'
import DrawButton from './DrawButton/DrawButton';
import firebase from 'firebase/app';
import 'firebase/database';

import { DB_CONFIG } from './Config/Firebase/db_config';


class App extends Component {
  constructor(props){
    super(props);

    
    if (!firebase.apps.length) {
    firebase.initializeApp(DB_CONFIG);
    this.database = firebase.database().ref().child('cards');
    }

    this.updateCard = this.updateCard.bind(this);

    this.state = {
      cards: [],
      currentCard: {}
    }
  }

  componentWillMount(){
    const currentCards = this.state.cards;
    this.database.on('child_added', snap => {
      currentCards.push({
        id: snap.key,
        ques: snap.val().ques,
        ans: snap.val().ans,
      })
      this.setState({
        cards: currentCards,
        currentCard: this.getRandomCard(currentCards)
      })
    })
  }
  getRandomCard(currentCards){
    var card = currentCards[Math.floor(Math.random() * currentCards.length)];
    return(card);
  }

  updateCard(){
    const currentCards = this.state.cards;
    this.setState({
      currentCard: this.getRandomCard(currentCards)
    })
  }
  render() {
    return (
      <div className="App">
        <div className="cardRow">
          <Card ques={this.state.currentCard.ques} 
                ans={this.state.currentCard.ans} 
          />
        </div>
        <div className="buttonRow">
          <DrawButton drawCard={this.updateCard}/>
        </div>   
      </div>
    );
  }
}

export default App;

Advertisement

Answer

this.database does not get assigned and is undefined since !firebase.apps.length returns false which probably means the Firebase app is initialized somewhere else. You should move the this.database assignment outside the if condition.

constructor(props) {
  super(props)

  if (!firebase.apps.length) {
    firebase.initializeApp(DB_CONFIG)
  }

  this.database = firebase.database().ref().child('cards')

  //...
}

I would recommend using the componentDidMount lifecycle hook to fetch data. Check this article for more information.

Advertisement