Skip to content

Latest commit

History

History
177 lines (136 loc) 路 4.83 KB

urql.mdx

File metadata and controls

177 lines (136 loc) 路 4.83 KB
title description nav
URQL
This doc describes URQL integration.
4.08

Install

You have to install jotai-urql, @urql/core and wonka to use the integration.

yarn add jotai-urql @urql/core wonka

Exported functions

All three functions follow the same signature.

const [dataAtom, statusAtom] = atomsWithSomething(
  query,
  getVariables,
  getContext,
  getClient
)

The first three parameters will be arguments to those functions (For mutation, it's empty). The last optional getClient parameter is a function that returns Client.

The return values have two atoms. The first one is called dataAtom and it's an atom for the data from the observer. dataAtom requires Suspense. The second one is called statusAtom and it's an atom for the full result from the observer. statusAtom doesn't require Suspnse. The data from the observer is also included in statusAtom, so if you don't use Suspense, you don't need to use dataAtom.

atomsWithQuery

atomsWithQuery creates new atoms with a query. It internally uses client.query.

import { useAtom } from 'jotai'
import { createClient } from '@urql/core'
import { atomsWithQuery } from 'jotai-urql'

const client = createClient({ url: '...' })

const idAtom = atom(1)
const [userAtom] = atomsWithQuery(
  '{ user { first_name last_name } }', // query
  (get) => ({ id: get(idAtom) }), // variables
  undefined, // context
  () => client
)

const UserData = () => {
  const [{ data }] = useAtom(userAtom)
  return <div>{JSON.stringify(data)}</div>
}

Examples

Basic demo

atomsWithMutation

atomsWithMutation creates new atoms with a mutation. It internally uses client.mutation.

import { useAtom } from 'jotai'
import { createClient } from '@urql/core'
import { atomsWithMutation } from 'jotai-urql'

const client = createClient({ url: '...' })

const [fooAtom] = atomsWithMutation(() => client)

const FooData = () => {
  const [{ data }, mutate] = useAtom(fooAtom)
  return (
    <div>
      {JSON.stringify(data)}{' '}
      <button
        onClick={() =>
          mutate({ query: 'mutation Foo { text }', variables: {} })
        }>
        Click me
      </button>
    </div>
  )
}

Examples

TODO: create example

atomsWithSubscription

atomsWithSubscription creates new atoms with a subscription. It internally uses client.subscription.

import { useAtom } from 'jotai'
import { createClient } from '@urql/core'
import { atomsWithSubscription } from 'jotai-urql'

const client = createClient({ url: '...' })

const [fooAtom] = atomsWithSubscription(
  'subscription Foo { text }', // query
  () => ({}), // variables
  undefined, // context
  () => client
)

const FooData = () => {
  const [{ data }] = useAtom(fooAtom)
  return <div>{JSON.stringify(data)}</div>
}

Examples

TODO: create example

Refferencing the same instance of the client for both atoms and urql provider

To ensure that you reference the same urqlClient object, be sure to wrap the root of your project in a <Provider> and initialise clientAtom with the same urqlClient value you provided to UrqlProvider.

Without this step, you may end up specifying client each time when you use atomsWithQuery. Now you can just ignore the optional getClient parameter, and it will use the client from the context.

import { Suspense } from 'react'
import { createStore } from 'jotai/vanilla'
import { Provider } from 'jotai/react'
import { clientAtom } from 'jotai-urql'

import {
  createClient,
  dedupExchange,
  cacheExchange,
  fetchExchange,
  Provider as UrqlProvider,
} from 'urql'

const urqlClient = createClient({
  url: 'https://countries.trevorblades.com/',
  exchanges: [dedupExchange, cacheExchange, fetchExchange],
  fetchOptions: () => {
    return { headers: {} }
  },
})

export default function MyApp({ Component, pageProps }) {
  const storeRef = useRef()
  if (!storeRef.current) {
    storeRef.current = createStore()
    storeRef.current.set(clientAtom, urqlClient)
  }
  return (
    <UrqlProvider value={urqlClient}>
      <Provider store={storeRef.current}>
        <Suspense fallback="Loading...">
          <Component {...pageProps} />
        </Suspense>
      </Provider>
    </UrqlProvider>
  )
}