tylermcginnis/re-base

Question: syncState with multiple db properties

LawrenceHunt opened this issue · 4 comments

Hey, I'm doing a little sport-themed app side project, and I'm liking the concept of synchronising all my app's state with firebase in the root component. However, it isn't entirely clear how to use syncState with multiple properties. Is there a better way to approach this than nested then() functions? For example, is there a way to return the promise such that I can use Promise.all() ?

This is what I currently have and it seems to work, but perhaps doesn't look all that elegant - especially if I extend it to 7 or 8 individual properties. Feels like I must be missing something basic.

componentWillMount() {
    this.teamsRef = base.syncState('teams', {
      context: this,
      state: 'teams',
      asArray: true,
      then: () => {
        this.fixturesRef = base.syncState('fixtures', {
          context: this,
          state: 'fixtures',
          asArray: true,
          then: () => {
            this.setState({loading: false})
          }
        })
      }
    })
  }

Thanks!

@LawrenceHunt They could all be on the same level and you could do this.setState({fixturesLoading: false}) , for example, to know when that specific listener was set. That way you don't have to wait before setting up the other listeners. syncState is kind of a black box, its tough to coordinate between multiple listeners so I don't think you are missing anything. then is just a callback so you could use it to increment a counter if you did want to wait for all the listeners to be set before flipping loading to false but it can't be used like a Promise.

@qwales1 Hi Chris, thanks so much for the response. To clarify, when you say 'they could all be on the same level', do you mean nesting them all inside one root state property?

I tried this but it felt wrong too - especially since Firebase advises as shallow data structures as possible?

@LawrenceHunt oh sorry no I meant not nesting the syncState calls inside each other. keeping them on the same "level" like

base.syncState('teams', {
  then() {
    this.setState({teamsLoading: false});
  }
});
base.syncState('fixtures', {
  then() {
    this.setState({fixturesLoading: false});
  }
});

I can go into more detail on my experience with the one root component approach, I have been thinking about doing a post or something. I also like the idea of it. It was the first thing I reached for and was like this looks like what I want. Data flows into the app from one place. The very short version of why I don't do that anymore is that it is very easy to end up basically rebuilding the firebase database in the local state of one component, but then lose all the defined methods for adding/updating/removing data that firebase provides. All of a sudden I had to think about "how do I keep data in sync" again and that is already solved by using Firebase. It took me a while before I didn't feel weird about having components subscribed all over the app, but my advice would be if it gets messy or feels not nice at all with one root and syncState don't hesistate to break it up. No matter what you do in the app the data is always flowing into your app from one place, the firebase sdk (under the hood of re-base in this case). I wish I was better at making diagrams 😆

Ah ok, thanks for the clarification - got it now! I will definitely try it as you suggest, the loading counters sound like a good idea. I first encountered this library through Wes Bos' React For Beginners tutorial, where the root App.js component is the store for everything. However it was such a simple app that only one state property needed to be synced.

A post would be very helpful! Also might be worth adding something about this to the Re-Base documentation, no?