Reputation: 1645
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;
Upvotes: 0
Views: 5764
Reputation: 3483
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');
Upvotes: 1