Yes. For example you can use SWR+socket.io (generally any subscription pattern) like this:
// fetch-data.js
import { mutate } from 'swr'
let latestData = null
// setup ws and broadcast to all SWRs
socket.on('data', data => {
latestData = data
mutate('/api/data', data, false)
})
export default () => latestData
and your component:
import useSWR from 'swr'
import fetchData from './fetch-data'
function App () {
const { data } = useSWR('/api/data', fetchData)
// ...
}
We need to document those use cases and best practices.
why did the old Subscription example be deleted? Is it wrong?
@hitbear518 oops, it should be a mistake I think. Going to add it again, thank you. 馃檹
I don鈥檛 see the subscriptions on the docs, are there any other recommendations for best practices? For instance, mounting and unmounting subscriptions during component clean ups. I assume the fetcher should be returned by a separate hook? Thanks!
Would something like this work?
// create-listener.ts
import { mutate } from 'swr'
import { db } from './db' // Firestore DB
export const createListener = (path: string) => {
let data = null
const unsubscribe = db.doc(path).onSnapshot(doc => {
data = doc.data()
mutate(path, doc.data(), false)
})
return {
latestData: () => data,
unsubscribe,
}
}
And then in a custom hook called useSubscription:
// use-subscription.ts
import { useRef, useEffect } from 'react'
import { createListener } from './create-listener'
export const useSubscription = (path: string) => {
const unsubscribeRef = useRef(null)
const swr = useSWR(path, path => {
if (unsubscribeRef.current) {
unsubscribeRef.current()
}
const { unsubscribe, latestData } = createListener(path)
unsubscribeRef.current = unsubscribe
return latestData()
})
useEffect(() => {
return () => {
// clean up the subscription if it exists
if (unsubscribeRef.current) {
unsubscribeRef.current()
unsubscribeRef.current = null
}
}
}, [path])
return swr
}
And, finally, in your component:
const { data } = useSubscription('users')
I would be very happy to see the official way of working with sockets in docs
This is exactly what I was looking for. But won't this call the subscriber multiple times causing many onSnapshot listeners? On blur/focus for example?
This is exactly what I was looking for. But won't this call the subscriber multiple times causing many onSnapshot listeners? On blur/focus for example?
If you鈥檙e referring to mine, notice that I store the unsubscribe variable in a ref, and call it whenever the function unmounts / the promise revalidates.
If you want to see a full example of swr sockets being used in production, you can see my library https://github.com/nandorojo/swr-firestore. Unfortunately it鈥檚 not the most simple code since it covers all things Firestore, so maybe I can add a tutorial at some point.
@nandorojo Nope, that was once again exactly what I was looking for! Thanks :)
Hello there!
cc @shuding
Any idea why the example with web sockets isn't in the examples? Did I miss something in this issue?
Am looking to add web sockets to an application and dont really know if I should just use normal state, or swr.
Thanks
Most helpful comment
Yes. For example you can use SWR+socket.io (generally any subscription pattern) like this:
and your component: