@Salakar I’m attempting to use the pattern you referenced in a previous issue.
The Problem
In my iOS app, it’s possible to have multiple instances of a component mounted at the same time.
Think Instagram – when a user taps a photo in Instagram and then taps the photo owner’s avatar, the user scene pushes in from the right.
If she then goes on to tap the same photo in the user’s list of photos, a clone of the first scene will also push in the from right.
In my app, all scenes need to mount, establish the Firebase listener, get a snapshot of the initial data and listen for changes after that.
Everything works great for the first component mounted. In any subsequent components, however, the listeners don’t immediately trigger the callback.
I suppose makes sense considering the docs:
Firebase data is retrieved by attaching an asynchronous listener to a firebase.database.Reference. The listener is triggered once for the initial state of the data and again anytime the data changes.
It’s as though Firebase sees each subsequent listener as the same listener and thus doesn’t trigger.
Data Structure
In my code, I’m following Firebase’s recommended data fan-out approach which seeks to create “data that scales.”
I’ve included the following JSON, so the complexity of the code that follows will be more clear.
{
"displayName" : "Andrew Henderson",
"host" : {
"-KgC-c0WvT0P1R-aDmVo" : true,
"-KgC0D94Cxs05GX8qWBc" : true,
"-KgC0s7f9lwweeDm3oeg" : true,
"-KgC0ypAODARXxvbva5F" : true
},
"puid" : "-Kg6pefxyFtyfPVe-aIo",
"timestamp" : 1490485162946,
"uid" : "H63dvD6TvJRZnpPwf9o0FejqmEf2"
}
Code
In my component, I set up a reference to a user’s posts which returns the host
object.
I then create a reference to all of the individual posts using those keys and receive the values for the full posts.
constructor(props) {
super(props);
const { uid } = props;
// Set firebase refs
this.postsRef = firebase.database().ref('posts');
this.hostsRef = firebase.database()
.ref(`users/${uid}/host`)
.orderByChild('startTime');
this.hostedPostRefs = {};
// Keep a raw copy of this user's posts
this.hostedPosts = {};
// ListView DataSource instance
this.hostedPostsDataSource = new ListView.DataSource({
rowHasChanged: (r1, r2) => r1._key !== r2._key,
});
// Initial State
this.state = {
loading: true,
hostedPostsDataSource: this.hostedPostsDataSource.cloneWithRows(this.hostedPosts),
};
}
componentDidMount() {
this.hostsRef.on('value', this._onHostsReceived)
}
componentWillUnmount() {
this.hostsRef.off();
forEach(this.hostedPostRefs, hostedPostRef => {
hostedPostRef.off()
})
}
_onHostsReceived = (snapshot) => {
snapshot.forEach(this._requestPost)
};
_requestPost = (snapshot) => {
const { key } = snapshot;
if (!this.hostedPostRefs[key]) {
this.hostedPostRefs[key] = this.postsRef.child(key);
this.hostedPostRefs[key].on('child_changed event', this._onPostReceived)
}
};
_onPostReceived = (snapshot) => {
this.hostedPosts[snapshot.key] = snapshot.val();
this.setState({
hostedPostsDataSource: this.hostedPostsDataSource.cloneWithRows(this.hostedPosts)
});
};
Correct.
In the case of firebase, google also provide native sdk’s for ios and android, which is what we use on the native side, therefore it’s just a case of mapping what the sdk functions has to the equivalent firebase native sdk function on ios or android, with a few things like data type conversions and error code/messages conversions inbetween. There’s also some special cases where the web sdk has no implementation of a native feature, for example, firebase native sdks have crash reporting and analytics but the web sdk doesn’t.
As far as I know react native modules ios wise are all objective-c based, don’t take my word on that though. Android wise it’s Java.
No I don’t think so, obviously with the first release it’s playing catch up to existing functionality, thereafter it’s shouldn’t be as much to do.
Tell me about it, we used firestack, eventually I ended up writing most of the v3 version of firestack before giving up with the lack of project maintenance from its owners and started this one. We use this in production apps so I don’t see this getting abandoned, also have a busy year ahead in terms of new apps that will make use of this, so keeping it up to date is in my best interest🙈