Skip to content

Instantly share code, notes, and snippets.

@reimertz
Last active May 3, 2023 02:57
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save reimertz/c6b7c61113b6847ae8e7c74b3dc673d6 to your computer and use it in GitHub Desktop.
Save reimertz/c6b7c61113b6847ae8e7c74b3dc673d6 to your computer and use it in GitHub Desktop.
RxJS + Firestore + React hooks basics
import { Observable, combineLatest } from 'rxjs'
import { startWith } from 'rxjs/operators'
import { useEffect, useState } from 'react'
export const docData = doc => {
const data = doc.data()
const idKey = data && data.id ? 'firebaseId' : 'id' // if original data contains an id..
return {
...data,
[idKey]: doc.id
}
}
export const ObservableFromRef = ref => {
return new Observable(subscriber => {
const unsubscribe = ref.onSnapshot(snapshot => subscriber.next(snapshot))
return () => unsubscribe()
})
}
export const useStream = (stream, initialValue = null) => {
const [current, setCurrent] = useState(initialValue)
useEffect(() => {
const sub = stream.subscribe(setCurrent)
return () => sub.unsubscribe()
}, [])
return current
}
import RNFirebase from '@react-native-firebase/app'
import { Observable, combineLatest } from 'rxjs'
import { shareReplay, map } from 'rxjs/operators'
import { docData, ObservableFromRef } from './utils'
const ObservableMap = new Map()
const dbRef = RNFirebase.firestore().collection('users')
export const allUsers = () => ObservableFromRef(dbRef).pipe(
map(snapshot => snapshot.docs),
map(docs => docs.map(docData)),
shareReplay(1)
)
export const user = id => {
if (!ObservableMap.has(id)) ObservableMap.set(id, ObservableFromRef(dbRef.doc(id)))
return ObservableMap.get(id).pipe(
map(doc => docData(doc)),
shareReplay(1)
)
}
import { ScrollView, Text } from 'react-native'
import { useStream } from './streams/utils'
import { allUsers } from './streams/users'
import { UserRow, UserDetail } from './components/Users'
export const UserList = props => {
const users = useStream(allUsers(), [])
return (
<ScrollView>
{ users.length > 0
? users.map(UserRow)
: <Text>No users exist.</Text>
}
</ScrollView>
)
}
export const UserDetail = ({ id }) => {
const user = useStream(user(id), null)
return (
{ user
? <UserDetail user={user} />
: <Text>No user found.</Text>
}
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment