DEV Community

Cover image for Consumindo uma API GraphQL com SWR
Vinicius Savegnago
Vinicius Savegnago

Posted on

Consumindo uma API GraphQL com SWR

SWR nos disponibiliza React Hooks para realizar requisições, com a estratégia de stale-while-revalidate de forma padrão. SWR consiste em a primeira vista, temos os dados do cache (stale) e enquanto isso,uma requisição é enviada (revalidate) para validar esse cache, e por fim, se houver alguma mudança, os dados são atualizados.

Sugiro a leitura das principais funcionalidades do SWR

SWR: React Hooks for Data Fetching

Sem mais enrolação, bora pro código!

 

Primeiro de tudo, vamos iniciar o nosso projeto e instalar o SWR

Vou utiilizar um template com Typescript

yarn create react-app swr-basics --template typescript
Enter fullscreen mode Exit fullscreen mode

Após o setup, vamos adcionar o SWR

yarn add swr
Enter fullscreen mode Exit fullscreen mode

Para todas as requisições que vamos utilizar o SWR, vamos precisar de uma fetcher function, que será uma função assíncrona que simplesmente retorna os dados. Para isso podemos utilizar tanto a API de fetch do próprio javascript, ou bibliotecas como axios. E para enviarmos requisições a APIs GraphQL, vamos precisar utilizar algum GraphQL Client

E nesse caso vamos usar o graphql-request

yarn add graphql-request graphql
Enter fullscreen mode Exit fullscreen mode

Além de todas essas libs, vamos precisar de alguma API GraphQL, para enviar nossas queries. Sendo assim, vamos utilizar uma API incrível da SpaceX

GraphiQL Explorer

Para começar, vamos enviar uma query buscando por foguetes 🚀

{
  rockets {
    active
    name
    mass {
      kg
    }
    description
  }
}
Enter fullscreen mode Exit fullscreen mode

Para isso, vamos criar o nosso componente que vai realizar a requisição e mostrar na tela os dados dos foguetes

Rockets.tsx

import { FunctionComponent } from "react";

const Rockets: FunctionComponent = () => {
  return (
    <div>
      <span>Rockets will land here</span>
    </div>
  );
};

export default Rockets;
Enter fullscreen mode Exit fullscreen mode

E nosso App.tsx vai ficar assim:

import "./app.css";
import Rockets from "./components/Rockets";

const App = () => {
  return (
    <div className="App">
      <Rockets />
    </div>
  );
};

export default App;
Enter fullscreen mode Exit fullscreen mode

Certo, agora pra que tudo funcione, vamos criar um arquivo com uma configuração básica do nosso GraphQL Client, onde vamos inserir a rota para a API da SpaceX

Também é possível adicionarmos outras opções, como headers, credentials, e etc...

graphqlClient.ts

import { GraphQLClient } from "graphql-request";

export const graphqlClient = new GraphQLClient(
  "https://api.spacex.land/graphql/"
);
Enter fullscreen mode Exit fullscreen mode

Com nosso cliente GraphQL, vamos começar enviando a nossa query

Para isso vamos criar a nossa fetcher function

Rockets.tsx

import { FunctionComponent } from "react";
import { RequestDocument } from "graphql-request/dist/types";
import { graphqlClient } from "../graphql/graphqClient";

const Rockets: FunctionComponent = () => {

  const fetcher = (query: RequestDocument) => graphqlClient.request(query)

  return (
    <div>
      <span>Rockets will land here</span>
    </div>
  );
};

export default Rockets;
Enter fullscreen mode Exit fullscreen mode

E esse RequestDocument será a nossa query que vamos enviar para buscar os foguetes

Podemos escreve-la assim:

const rocketsQuery = `
    {
      rockets {
        active
        name
        mass {
          kg
        }
        description
      }
    }
  `
Enter fullscreen mode Exit fullscreen mode

E tudo que precisamos fazer é passar ela para o hook useSWR, juntamente com a nossa função fetcher

E desse hook podemos obter data e error

const { data, error } = useSWR(rocketsQuery, fetcher)
Enter fullscreen mode Exit fullscreen mode

E podemos mostrar na tela se existir algum dado:

if (data) {
    return (
      <div>
        <pre>{JSON.stringify(data, null, 2)}</pre>
      </div>
    );
  }
Enter fullscreen mode Exit fullscreen mode

Rockets.tsx

import { FunctionComponent } from "react";
import { RequestDocument } from "graphql-request/dist/types";
import { graphqlClient } from "../graphql/graphqClient";
import useSWR from "swr";

const Rockets: FunctionComponent = () => {
  const fetcher = (query: RequestDocument) => graphqlClient.request(query);

  const rocketsQuery = `
    {
      rockets {
        active
        name
        mass {
          kg
        }
        description
      }
    }
  `;

  const { data, error } = useSWR(rocketsQuery, fetcher);

  if (data) {
    return (
      <div>
        <pre>{JSON.stringify(data, null, 2)}</pre>
      </div>
    );
  }

  if (error) {
    return (
      <div>
        <pre>Something went bad :(</pre>
      </div>
    );
  }

  return (
    <div>
      <span>Loading rockets...</span>
    </div>
  );
};

export default Rockets;
Enter fullscreen mode Exit fullscreen mode

Se tudo ocorreu bem, teremos um JSON com os foguetes

Rockets JSON

Irado! 🤘🏼

 

Agora que já pegamos a ideia da coisa, vamos enviar uma mutation para a API, criando um usuário

A mutation vai ser assim:

mutation {
  insert_users(objects: {name: "Vinicius", rocket: "El Jalapeño Rocket"}) {
    returning {
      id
      name
      rocket
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

E a query para buscar os usuáros

{
  users {
    id
    name
    rocket
  }
}
Enter fullscreen mode Exit fullscreen mode

Então bora começar criando um componente para listar os usuários

E assim como nossa query de foguetes, vamos criar nossa fetcher function, adicionar nossa query de usuários, e por fim, nosso hook useSWR

Users.tsx

import { FunctionComponent } from "react";
import { RequestDocument } from "graphql-request/dist/types";
import { graphqlClient } from "../graphql/graphqClient";
import useSWR from "swr";

const Users: FunctionComponent = () => {
  const fetcher = (query: RequestDocument) => graphqlClient.request(query);

  const usersQuery = `
    {
        users {
            id
            name
            rocket
        }
    }

  `;

  const { data, error } = useSWR(usersQuery, fetcher);


  ...

};

export default Users;
Enter fullscreen mode Exit fullscreen mode

Agora vamos colocar na tela os usuários, e enquanto eles não aparecem, podemos mostrar um "Loading..." na tela

Users.tsx

if (data) {
    return (
      <div>
        <div>
          <pre>{JSON.stringify(data, null, 2)}</pre>
        </div>
      </div>
    );
  }

  if (error) {
    return <div>Something went bad!</div>;
  }

  return (
    <div>
      <span>Loading Users...</span>
    </div>
  );
Enter fullscreen mode Exit fullscreen mode

Então, temos um JSON com os usuários

Users JSON

Nice! 🤘🏼

 

Por fim, vamos criar um formulário para adicionar um novo usuário, e ver se ele aparece na nossa lista de usuários

UserForm.tsx

import { FormEvent, FunctionComponent, useState } from "react";

const UserForm: FunctionComponent = () => {
  const [username, setUsername] = useState<string>("");
  const [rocketName, setRocketName] = useState<string>("");

  const handleCreateuser = async (event: FormEvent<HTMLFormElement>) => {
    event.preventDefault();

    console.log({username, rocketName})
  };

  return (
    <form onSubmit={(event) => handleCreateuser(event)}>
      <input
        type="text"
        placeholder="username"
        value={username}
        onChange={(event) => setUsername(event.target.value)}
      />
      <input
        type="text"
        placeholder="rocket name"
        value={rocketName}
        onChange={(event) => setRocketName(event.target.value)}
      />
      <button>Create User</button>
    </form>
  );
};

export default UserForm;
Enter fullscreen mode Exit fullscreen mode

Por enquanto, nosso componente está apenas fazendo um log com os valores dos inputs

Agora precisamos criar uma mutation, passando esses valores

Essa é a mutation para inserir usuários

mutation insertUsers($name: String!, $rocket: String!){
            insert_users(objects: {name: $name, rocket: $rocket}) {
                returning {
                    id
                    name
                    rocket
                }
            }
        }
Enter fullscreen mode Exit fullscreen mode

E agora junto com a mutation, utlizando o graphql-request, vamos passar as variáveis que vamos criar o usuário

UserForm.tsx

const [username, setUsername] = useState<string>("");
const [rocketName, setRocketName] = useState<string>("");

const createUserMutation = `
        mutation insertUsers($name: String!, $rocket: String!){
            insert_users(objects: {name: $name, rocket: $rocket}) {
                returning {
                    id
                    name
                    rocket
               }
           }
      }
 `;

const handleCreateuser = async (event: FormEvent<HTMLFormElement>) => {
    event.preventDefault();

    const response = await graphqlClient.request(createUserMutation, {
      name: username,
      rocket: rocketName,
    });

    console.log(response);
  };
Enter fullscreen mode Exit fullscreen mode

Agora assim que enviarmos a nossa mutation, nossa query de users vai notar que houve uma mudança, e irá revalidar os dados, carregando o nosso novo usuário na tela.

Então o resultado final será esse:

UserForm.tsx


import { FormEvent, FunctionComponent, useState } from "react";
import { graphqlClient } from "../graphql/graphqClient";

const UserForm: FunctionComponent = () => {
  const [username, setUsername] = useState<string>("");
  const [rocketName, setRocketName] = useState<string>("");

  const createUserMutation = `
        mutation insertUsers($name: String!, $rocket: String!){
            insert_users(objects: {name: $name, rocket: $rocket}) {
                returning {
                    id
                    name
                    rocket
                }
            }
        }
    `;

  const handleCreateuser = async (event: FormEvent<HTMLFormElement>) => {
    event.preventDefault();

    const response = await graphqlClient.request(createUserMutation, {
      name: username,
      rocket: rocketName,
    });

    console.log(response);
  };

  return (
    <form onSubmit={(event) => handleCreateuser(event)}>
      <input
        type="text"
        placeholder="username"
        value={username}
        onChange={(event) => setUsername(event.target.value)}
      />
      <input
        type="text"
        placeholder="rocket name"
        value={rocketName}
        onChange={(event) => setRocketName(event.target.value)}
      />
      <button>Create User</button>
    </form>
  );
};

export default UserForm;


Enter fullscreen mode Exit fullscreen mode

E podemos fazer um teste:

E após enviarmos o formulário, a nossa query de users vai revalidar a requisição e assim que tiver algum novo usuário, vamos ter a atualização na tela.

Users JSON with created User

Incrível! 🔥

Espero que agora as requisições para APIs GraphQL utilizando SWR tenha ficado mais claro. E caso precise de alguma ajuda, mande uma mensagem 👍🏼

 

Se esse post foi útil, e te ajudou de alguma maneira, deixe uma reação e me siga nas redes.

vinisaveg - Github

Vinicius Savegnago - LinkedIn

 

Happy Coding!

Links úteis:

vinisaveg/swr-basics

SWR: React Hooks for Data Fetching

prisma-labs/graphql-request

Top comments (1)

Collapse
 
ubmit profile image
Guilherme de Andrade

Obrigado pelos exemplos!