SWR with graphql-request how to add variables in swr?

Viewed 2416

I want to add variables to my swr which fetch using graphql request. this is my code

import { request } from "graphql-request";
import useSWR from "swr";

const fetcher = (query, variables) => request(`https://graphql-pokemon.now.sh`, query, variables);

export default function Example() {
  const variables = { code: 14 };
  const { data, error } = useSWR(
    `query GET_DATA($code: String!) {
                getRegionsByCode(code: $code) {
                  code
                  name
                }
              }`,
    fetcher
  );

  if (error) return <div>failed to load</div>;
  if (!data) return <div>loading...</div>;
  return <pre>{JSON.stringify(data, null, 2)}</pre>;
}

but I dont know how to add variables into swr fetcher as I know useSWR(String, fetcher) string is for query, and fetcher for fetch function, where I can put the variables?

3 Answers

You can use Multiple Arguments, you can use an array as the key parameter for the useSWR react hook.

import React from "react";
import { request } from "graphql-request";
import useSWR from "swr";

const fetcher = (query, variables) => {
  console.log(query, variables);
  return request(`https://graphql-pokemon.now.sh`, query, variables);
};
export default function Example() {
  const variables = { code: 14 };
  const { data, error } = useSWR(
    [
      `query GET_DATA($code: String!) {
          getRegionsByCode(code: $code) {
            code
            name
          }
        }`,
      variables,
    ],
    fetcher
  );

  if (error) return <div>failed to load</div>;
  if (!data) return <div>loading...</div>;
  return <pre>{JSON.stringify(data, null, 2)}</pre>;
}

The function fetcher still accepts the same 2 arguments: query and variables.

SWR author here!

Agreed that this is a critical feature to have, that's why since v1.1.0, SWR keys will be serialized automatically and stably. So you can safely do this:

useSWR(['query ...', variables], fetcher)

While variables can be a JavaScript object (can be nested, or an array, too), and it will not cause any unnecessary re-renders. Also, the serialization process is stable so the following keys are identical, no extra requests:

// Totally OK to do so, same resource!
useSWR(['query ...', { name: 'foo', id: 'bar' }], fetcher)
useSWR(['query ...', { id: 'bar', name: 'foo' }], fetcher)

You can directly pass an object as the key too, it will get passed to the fetcher:

useSWR(
  {
    query: 'query ...',
    variables: { name: 'foo', id: 'bar' }
  },
  fetcher
)

You can try it out by installing the latest version of SWR, let me know if there's any issue :)

The solution from slideshowp2 did not help me since it resulted in an infinite loop.

Don't pass an object to the useSWR function since they change on every re-render. Pass the variables directly:

const fetcher = (query, variables) => {
  console.log(query, variables);
  return request(`https://graphql-pokemon.now.sh`, query, variables);
};
export default function Example() {
  const { data, error } = useSWR(
    [
      `query GET_DATA($code: String!) {
          getRegionsByCode(code: $code) {
            code
            name
          }
        }`,
      14,
    ],
    (query, coder => fetcher(query, { code })
  );

  if (error) return <div>failed to load</div>;
  if (!data) return <div>loading...</div>;
  return <pre>{JSON.stringify(data, null, 2)}</pre>;
}
Related