简体   繁体   中英

React & Firebase + Flux : Child component does not render

I've already checked this SO article , however, the solution does not work. I have a simple messaging app using Firebase + Flux:

App
-UserList Component (sidebar)
-MessageList Component

The UserList component gets props from this.state.threads (state belongs to main App component).

In my Flux ThreadStore, I have the following event listeners bound to a firebaseRef:

const _firebaseThreadAdded = (snapshot) => {
    threadsRef.child(snapshot.key()).on('value', (snap) => {
        console.log('thread added to firebase');
        _threads.push({
            key: snap.key(),
            threadType: snap.val().threadType,
            data: snap.val()});
    });
}

ref.child(ref.getAuth().uid).child('threads').on('child_added', Actions.firebaseThreadAdded);

The UserList uses this.props.threads.map(thread => { return(<li>{thread.name}</li>) } ) (summarised) to then render a list of thread names in the side bar based on the thread keys in the firebaseRef/userId/threads.

However, this does not render any list of users until I click any button in the app or delete a reference directly from the Firebase Forge UI (I also have a 'child_removed' event listener).

For the life of me I cannot figure this out. Can anyone explain why this is happening / how to fix it? I've spent a whole half day trying and haven't come up with anything.

FYI:

  1. Relevant Dispatcher.register entry:

     case actionConstants.FIREBASE_THREAD_ADDED: _firebaseThreadAdded(action.data); threadStore.emitChange(); break; 
  2. Relevant Actions entry:

     firebaseThreadAdded(data) { AppDispatcher.handleAction({ actionType: actions.FIREBASE_THREAD_ADDED, data }); }, 

Okay, so I figured it out after a lot of reading - a little new to Flux. The issue was here:

case actionConstants.FIREBASE_THREAD_ADDED:
        _firebaseThreadAdded(action.data);
        threadStore.emitChange();
        break;

The emitChange() action was being triggered before the Firebase promise was being resolved, and hence the child components were updating hte state without any data. Hence, the list was not being rendered. What I did to change this was re-architect the function so that threadStore.emitChange() would only be triggered on resolve:

const _firebaseThreadAdded = (snapshot) => {
    threadsRef.child(snapshot.key()).once('value').then(snap => {
        console.log('thread added to firebase: ', snap.key());
        _threads.push({
            threadId: snap.key(),
            threadType: snap.val().threadType,
            data: snap.val()});
        threadStore.emitChange();
    });
}

and the resulting dispatcher register entry:

case actionConstants.FIREBASE_THREAD_ADDED:
            _firebaseThreadAdded(action.data);
            break;

Don't know if this is the best way of handling this, but it's doing the job - the emit event is only triggered once firebase has loaded. Hope this helps anyone with a similar issue for promises/firebase/ajax!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM