В качестве предисловия я только начинаю погружаться в 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;



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Проблема здесь:
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.apps.length) понадобилось? Интересно, должен ли я каждый раз проверять, инициализировалось ли приложение?
Отлично, имеет смысл, решено, но все же нужен
firebase.initializeApp(DB_CONFIG);внутриif (!firebase.apps.length)