Ошибка React / Firebase: не удается прочитать базу данных свойства undefined

В качестве предисловия я только начинаю погружаться в React.js, поэтому решение может быть простым.

Я использую React.js с firebase и response-router для базового многостраничного сайта с формой, которая публикует текст. На странице TicketList я пытаюсь отправить данные в Firebase, что работает, но когда я перехожу на другую страницу и возвращаюсь на страницу TicketList, я получаю сообщение об ошибке: TypeError: Cannot read property 'database' of undefined.

Из учебника, которому я следую, код тот же, за исключением того, что весь мой код TicketList находится на App.js, поскольку в учебнике не было реактивного маршрутизатора. Не уверен, связана ли эта структура с этой проблемой. В руководстве также нет this.app = firebase.initializeApp(DB_CONFIG); внутри if (!firebase.apps.length), но без этого бита я получаю сообщение об ошибке: Firebase App named '[DEFAULT]' already exists.

Если я помещаю this.database = this.app.database().ref().child('tickets'); внутрь if (!firebase.apps.length), я получаю сообщение об ошибке: TypeError: Cannot read property 'on' of undefined, но теперь я думаю, что слишком далеко ухожу от исходной проблемы, и я думаю, что мое понимание неверно. У кого-нибудь есть направление для меня? Спасибо!

Структура:

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;
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
0
4 469
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Проблема здесь:

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

firebase.initialize является асинхронным, поэтому this.app не определен к тому моменту, когда вы на него ссылаетесь.

вместо этого попробуйте:

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

Отлично, имеет смысл, решено, но все же нужен firebase.initializeApp(DB_CONFIG); внутри if (!firebase.apps.length)

douglasrcjames 09.08.2018 21:03

Не возражаете, если я спрошу, зачем там (! Firebase.apps.length) понадобилось? Интересно, должен ли я каждый раз проверять, инициализировалось ли приложение?

Stephanos 22.12.2020 16:49

Другие вопросы по теме