Swr: Support socket request like sockjs-client or socket.io ?

Created on 30 Oct 2019  路  11Comments  路  Source: vercel/swr

documentation

Most helpful comment

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)
  // ...
}

All 11 comments

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

Was this page helpful?
0 / 5 - 0 ratings

Related issues

bcomnes picture bcomnes  路  3Comments

Svish picture Svish  路  5Comments

DoT214 picture DoT214  路  4Comments

dandrei picture dandrei  路  3Comments

loveholly picture loveholly  路  3Comments