Reputation: 77
I am hoping to display a list of user's notes from a Firebase DB inside of a React app.
After reading through the Firebase recommended approach on structuring data, I've created my database in the flattened format they recommend. The data structure looks something like this:
notes
- [noteKey]
- note: [noteData]
- created_at: [date]
- updated_at: [date]
...
users
- [userKey]
- name: [userName]
- notes
- [noteKey]: true
...
...
Each user has an array called notes, which lists the noteKeys of the notes that they own.
So far I've been able to get the full list of notes (from all users, not what I want), and the user's list of noteKeys. The issue that I'm having is combining those two. I have seen the question about joining tables, but I have more of a React focused question:
In which React function does the join happen?
Right now my code looks like this:
getInitialState: function(){
return {
notesList: []
};
},
componentWillMount: function() {
base = Rebase.createClass('https://appName.firebaseio.com');
base.syncState('notes', {
context: this,
state: 'notesList',
asArray: true,
queries: {
limitToLast: 20
}
});
this.state.notesList.map(function(item, i) {
base.child("notes/" + item['.key'] + "/note").on('child_added', function(snapshot) {
console.log(item['.key'])
});
});
},
I see two issues with this.
this.state.notesList.map
function is called in componentWillMount
, the array hasn't been populated with the Firebase data yet, so it looks like an empty array and returns an error. --
Upvotes: 1
Views: 1406
Reputation: 20554
You're working with an async library (re-base) here but you've written synchronous code.
What this means is base.syncState
is going to fire off a request to your Firebase instance and in the meantime, your JavaScript is going to just keep happily executing down the line with or without results. It follows that this.state.notesList.map
is going to map over an empty array since JS is going to execute faster than a round trip to the server.
Looking at the options available for the syncState method, there's one called then
that executes a callback.
then: (function - optional) The callback function that will be invoked when the initial listener is established with Firbase. Typically used (with syncState) to change this.state.loading to false.
This makes me think that it fires after you get your data from Firebase.
Try running your .map
in there since you'll actually have the data you want.
componentWillMount: function() {
base = Rebase.createClass('https://appName.firebaseio.com');
base.syncState('notes', {
context: this,
state: 'notesList',
asArray: true,
queries: {
limitToLast: 20
},
then: function() {
this.state.notesList.map(function(item, i) {
base.child("notes/" + item['.key'] + "/note").on('child_added', function(snapshot) {
console.log(item['.key'])
});
});
}
});
}
Upvotes: 1