RevereCRE / relay-nextjs

⚡️ Relay integration for Next.js apps
https://reverecre.github.io/relay-nextjs/
MIT License
251 stars 30 forks source link

relay-nextjs with Subscriptions - Live Queries #54

Closed AngelLoredoAlvarez closed 2 years ago

AngelLoredoAlvarez commented 2 years ago

I was wondering if it is possible to make use of Subscriptions - Live Queries with graphql-ws, they offer an example using Relay Modern, but I am not pretty sure that their implementation will work properly with Next and SSR.

rrdelaney commented 2 years ago

Although I haven't tested this functionality myself, it definitely seems possible from reading the docs! relay-nextjs doesn't have any say on how you structure your network, so it should work as normal.

petrbela commented 2 years ago

Just add it to your client environment like so:

// getClientEnvironment.ts
import { createClient } from 'graphql-ws'
import { getRelaySerializedState } from 'relay-nextjs'
import { withHydrateDatetime } from 'relay-nextjs/date'
import {
  Environment,
  Network,
  Observable,
  RecordSource,
  Store,
} from 'relay-runtime'

export function createClientNetwork() {
  const ws = process.env.NEXT_PUBLIC_API_URL?.replace('http', 'ws')
  const wsClient = createClient({ url: ws + '/graphql' })

  return Network.create(
    async (params, variables) => {
      const response = await fetch(
        `${process.env.NEXT_PUBLIC_API_URL}/graphql`,
        {
          method: 'POST',
          credentials: 'include',
          headers: {
            'Content-Type': 'application/json',
          },
          body: JSON.stringify({
            query: params.text,
            variables,
          }),
        }
      )

      const json = await response.text()
      return JSON.parse(json, withHydrateDatetime)
    },
    (operation, variables) =>
      Observable.create((sink) =>
        wsClient.subscribe(
          {
            operationName: operation.name,
            query: operation.text!,
            variables,
          },
          sink as any
        )
      )
  )
}

let clientEnv: Environment | undefined

export function getClientEnvironment() {
  if (typeof window === 'undefined') return null

  if (clientEnv == null) {
    clientEnv = new Environment({
      network: createClientNetwork(),
      store: new Store(new RecordSource(getRelaySerializedState()?.records)),
      isServer: false,
    })
  }

  return clientEnv
}
rrdelaney commented 2 years ago

@petrbela Thanks for the example! Knowing that relay-nextjs doesn’t get in the way of using this feature, I’m going to close this issue. Please re-open if it doesn’t work for you