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.--
--
You received this message because you are subscribed to the Google Groups "Firebase Google Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to firebase-tal...@googlegroups.com.
To post to this group, send email to fireba...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/firebase-talk/846cec02-e282-4d12-9431-3e5281be4458%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
To view this discussion on the web visit https://groups.google.com/d/msgid/firebase-talk/0efb85c0-3a08-4ede-95b8-66540cd2da8a%40googlegroups.com.
"notes" : {
"n1" : {
"note" : "[noteData]",
"created_at" : "[date]",
"updated_at" : "[date]",
}
},
"users" : {
"userOne" : {
"name" : "[userName]",
"notes" : {
"n1" : true
}
}
}"users" : {
"userOne" : {
"name" : "[userName]",
"notes" : {
"n1" : <note_title>
}
}To view this discussion on the web visit https://groups.google.com/d/msgid/firebase-talk/b071158e-7d8e-4ed5-89f4-9e1f42d69bdc%40googlegroups.com.
"users" : {
"userOne" : {
"name" : "[userName]",
"notes" : { "n1" : { "title" : <note_title>, "created_at" : <created_at>, "updated_at" : <updated_at>, "note_preview" : <note_preview>
}
}To view this discussion on the web visit https://groups.google.com/d/msgid/firebase-talk/01a2404c-0a70-42ee-b0ad-e97e7a0da18a%40googlegroups.com.
For your use case, every note probably only corresponds to a single user. So you don't have the same problem exactly. If you find that the data you are storing to show the preview is almost the same as the data to show the entire note, you might just want to avoid the denormalization and store all the data under the /users node.
if you are a movie rating site, it doesn't make sense to copy all the movie information under each user who has reviewed that movie. Instead, you should just store the movie ID and store all the data in a /movies node.
Get all of a Users Note keys (ie. userID.noteKeys.[notekey]) { For each note key, find the corresponding Note object and return it (ie. Notes.[noteKey]) Add the returned Note object into this.state.notes}...
// src/browser/app/App.js React component
componentDidMount() {
const {actions: {onload}} = this.props;
onload();
}
// src/common/onload/actions.js
// get the onload function renamed to afterLoad here since UI gets rehydrated
import afterLoad from '../onload';
export const ONLOAD = 'ONLOAD';
export const ONLOAD_SUCCESS = 'ONLOAD_SUCCESS';
export const ONLOAD_ERROR = 'ONLOAD_ERROR';
export function onload() {
return ({firebase, settings: {s3BucketUrl}}) => {
console.log('onload actions s3BucketUrl', s3BucketUrl);
return ({
type: 'ONLOAD',
payload: {
promise: afterLoad(firebase),
},
});
};
}// src/common/onload/reducer.jsimport {Record} from 'immutable';Then there are reducers for the other reducers for the other top level objects, like inside of:
import {ONLOAD_ERROR} from './actions';
const InitialState = Record({
error: null
});
const initialState = new InitialState;
export default function onloadReducer(state = initialState, action) {
switch (action.type) {
case ONLOAD_ERROR: {
console.error('ONLOAD_ERROR action.payload.error', action.payload.error);
return state.set('error', action.payload.error);
}
}
return state;
}
// src/common/users/reducer.jsexport default function usersReducer({settings}) {
return function returnedUsersReducer(state = initialState, action) {
console.log('returnedUsersReducer action', action);
if (!(state instanceof InitialState)) {
const newState = revive(state, settings.s3BucketUrl);
return newState;
}
switch (action.type) {
case ONLOAD_SUCCESS: {
const users = setupData(action.payload.users, settings.s3BucketUrl, state.viewer);
return state.mergeDeep(users);
}...