Typescript
Generics, optionele parameters, typeof en veel meer
const handleUpdate = useCallback(
async (
docId: string,
data: Partial<T>,
options?: {
batch?: Firebase.firestore.WriteBatch,
}
) => {
options?.batch
? options.batch.update(collection.doc(docId), data)
: await collection.doc(docId).update(data);
if (!options || !options.batch) {
setState((d) => {
const index = d.docs.findIndex((doc) => doc.id === docId);
d.docs[index] = {
...d.docs[index],
...data,
};
return {
loading: d.loading,
docs: [...d.docs],
};
});
}
},
[collection]
);
Google Firebase implementatie
Collectie data ophalen met een react custom hook.
export function useCollection<T extends {}>(collectionPath: string, queryCallback?: (collection: Firebase.firestore.CollectionReference) => Firebase.firestore.Query | Firebase.firestore.CollectionReference) {
const [{ docs, loading }, setState] = useState<{ loading: boolean, docs: Array<T & { id: string }> }>({ loading: false, docs: [] })
const firestore = useFirestore()
const collection = useMemo(() => firestore.collection(collectionPath), [firestore, collectionPath])
useEffect(() => {
setState({ loading: true, docs: [] })
const snapshot = queryCallback ? queryCallback(collection).get() : collection.get()
snapshot.then(s => {
setState(() => ({ loading: false, docs: s.docs.map(doc => ({ id: doc.id, ...doc.data() as T })) }))
})
}, [collection, queryCallback])
Authenticatie event afluisteren en state wijzigen
export function useFirebaseAuthUser(authStateChangedCallback?: (user: Firebase.User | null) => void) {
const [user, setUser] = useState<Firebase.User | null>(null)
const auth = useAuth()
useEffect(() => {
auth.onAuthStateChanged(user => {
setUser(user)
authStateChangedCallback && authStateChangedCallback(user)
})
}, [auth, authStateChangedCallback])
return user
}
React Material UI
<AutComplete /> component om treinstation locaties op te zoeken
import { useLazyQuery } from '@apollo/client'
import { TextField } from '@material-ui/core'
import { Autocomplete } from '@material-ui/lab'
import React, { useCallback, useEffect, useMemo } from 'react'
import { QUERY_PLACES } from '../queries'
let timeout: NodeJS.Timeout
function PlaceSearch<T extends { name: string, type: string }>({ endAdornment, label, margin, value, onChange }: { endAdornment?: React.ReactNode, label: React.ReactNode, margin?: 'dense' | 'none' | 'normal', value: T | null, onChange: (event: React.ChangeEvent<{}>, value: T | null) => void }) {
const [getPlaces, { loading, data }] = useLazyQuery<{ places: T[] }>(QUERY_PLACES)
useEffect(() => {
return function cleanup() {
clearTimeout(timeout)
}
}, [])
const search = useCallback((q: string) => {
if (value) {
getPlaces({ variables: { q: value.name } })
} else {
clearTimeout(timeout)
timeout = setTimeout(() => {
if (q.length > 2) {
getPlaces({ variables: { q } })
}
}, 500)
}
}, [getPlaces, value])
const filteredOptions = useMemo(() => {
if (data) {
const stations = data.places.filter(({ type }) => type === 'stationV2')
return stations.length > 0 ? stations : data.places
}
return []
}, [data])
return <Autocomplete
renderInput={(props) => (
<TextField
{...props}
label={label}
margin={margin}
variant="outlined"
InputProps={{ ...props.InputProps, style: { paddingRight: 8 }, endAdornment }}
/>
)}
value={value}
loading={loading}
loadingText="Zoeken..."
noOptionsText="Zoek naar een station"
onChange={onChange}
onInputChange={(e, v) => search(v)}
options={filteredOptions}
getOptionLabel={opt => opt.name}
getOptionSelected={(opt, v) => opt.name === v.name}
/>
}
export default PlaceSearch
NS Api stations ophalen en in de state zetten
export async function getPlaces(q?: string, station_code?: string, lat?: number, long?: number) {
const find = q ? { q } : station_code ? { station_code } : { lat, lng: long }
const response = await fetch(`${apiUrl}/places-api/v2/places?limit=100&${serialize(find)}&radius=5000&lang=nl&type=stationV2`, { headers }) // removed: stop,address
const data: { payload: any[] } = await response.json()
return data.payload.reduce((places, { type, locations }) => {
locations.forEach(({ stationCode, UICCode, link, name, lat, lng, ...rest }: any) => places.push({ ...rest, name, UICCode, stationCode, link: link.uri, type, position: { lat, long: lng } }))
return places
}, [])
}
![](https://www.theuy.nl/content/images/2021/04/116150564-cd795500-a6e3-11eb-8b73-d4baa9f972fc.jpeg)
![](https://www.theuy.nl/content/images/2021/04/116150525-c2bec000-a6e3-11eb-8836-931cb7059f6a.jpeg)
![](https://www.theuy.nl/content/images/2021/04/116151167-8f306580-a6e4-11eb-9913-132b90cd3cd5.jpeg)
Meer code voorbeelden:
some hooks wrapping firebase client lib
some hooks wrapping firebase client lib. GitHub Gist: instantly share code, notes, and snippets.
![](https://github.githubassets.com/images/modules/gists/gist-og-image.png)
Travel assistent project i’ve been working on recently
Travel assistent project i’ve been working on recently - NSApi.ts
![](https://github.githubassets.com/images/modules/gists/gist-og-image.png)