IjzerenHein / firestorter

Use Google Firestore in React with zero effort, using MobX 🤘
http://firestorter.com
MIT License
378 stars 50 forks source link

Loading without observables #74

Closed RWOverdijk closed 5 years ago

RWOverdijk commented 5 years ago

I'm guessing this has to do with the observer...

My case: I have an overview of chats. For each chat I want to load the last message from a collection so I can show it in the overview.

So I do this:

messageCollection = new Collection(() => `${props.path}/messages`, {
  query: (ref: any) => ref.limit(1).orderBy('createdAt', 'desc')
});

And try to access it in render like this:

messageCollection.docs[0]

But it's undefined.

However, it does work when I use map.

I just want the first result, so it's not ideal.

Workaround

This approach works, but perhaps there's a nicer way of doing it.

subtitle={messageCollection.docs.map(message => message.data.text).join('')}

Other cases

Being able to tell firestorter when it's time to listen and when to stop could also benefit the mapping of data.

For example, https://github.com/FaridSafi/react-native-gifted-chat has a pretty weird data format and wants ids to be underscored, etc. I have to map those to other formats. Even if I didn't, it expects an array. Because it's not observed now, no data is loaded.

Again a workaround for this is using map like so:

<GiftedChat
  messages={messageCollection.docs.map(doc => doc.data)}
  /* ... */
/>

PS: Good morning. Sorry for all the emails. Sometimes I get overexcited when I find a fun new toy.

IjzerenHein commented 5 years ago

Hi Roberto,

I would have expected docs[0] to have worked to be honest. Can you share a more elaborate example?

I also (almost exclusively) use FIrestorter with react-native, and there are some cases which you need to be aware of. One of them is when using FlatList for instance. FlatList will store the docs array reference but not access its contents from render. This causes the observable to not be tracked when changes happen. In that case, doing a docs.slice(0) will fix that problem. Are you using a FlatList style list?

RWOverdijk commented 5 years ago

@IjzerenHein Thanks for your reply.

For now my workaround is fine for me, and because of deadlines I'll leave it be. I know, it's bad but... In the future I'll probably encounter it again and make an example. The best I can do is the snippet I posted above. The map works, whereas the index accessor doesn't.

Regarding flatlist, I am. The map works though, even when there are changes, it updates. I'm pretty sure that's because I always create a new array (.map()). Is that a bug then? Am I lucky? Or are there side-effects that'll come to haunt me?

IjzerenHein commented 5 years ago

I guess that it works because map() causes an access on the array, leading to an observable reaction to be established. I didn't know you could use map without a input function though.

Another thing to be aware of, is that your rendered items should be an explicit component which is wrapped with observer. When you don't do this, the item will not be updated when just the document content changes.

RWOverdijk commented 5 years ago

☝️ that makes sense.

That's not a problem for me because I'm recreating the array on every change. I know it's not ideal, but there's not that much data to be displayed so eh...

Consider me informed.

RWOverdijk commented 5 years ago

@IjzerenHein You said:

FlatList will store the docs array reference but not access its contents from render. This causes the observable to not be tracked when changes happen. In that case, doing a docs.slice(0) will fix that problem.

I just found something that imo explains more and solves it more elegantly, thought you might like to know. And if you knew already, well, I tried being nice haha. https://github.com/mobxjs/mobx/issues/1142#issuecomment-323161298