<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Drago</title>
    <description>The latest articles on Forem by Drago (@drago).</description>
    <link>https://forem.com/drago</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F612306%2F42ff0f59-20bb-4537-b4b6-6937d2ae768d.jpg</url>
      <title>Forem: Drago</title>
      <link>https://forem.com/drago</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/drago"/>
    <language>en</language>
    <item>
      <title>Comprehensive guide to GraphQL clients, part 3</title>
      <dc:creator>Drago</dc:creator>
      <pubDate>Sun, 17 Apr 2022 05:17:20 +0000</pubDate>
      <link>https://forem.com/drago/comprehensive-guide-to-graphql-clients-part-3-12g0</link>
      <guid>https://forem.com/drago/comprehensive-guide-to-graphql-clients-part-3-12g0</guid>
      <description>&lt;h2&gt;
  
  
  React-Relay
&lt;/h2&gt;

&lt;p&gt;Relay is a GraphQL client which is built by Facebook. It is a great GraphQL client, but it is not a good choice for simple applications and beginners. It is highly opinionated, users must follow the strict rules.&lt;br&gt;
The main thing here is that the error possibility is minimal. Contrary to other clients it misses a lot of flexibility. Relay demands a lot of knowledge about the application and schema design.&lt;br&gt;
The shiny point is that it is awesome for scalability. Relay is a complete framework for declarative data fetching.&lt;br&gt;
To be able to use Relay, one must create a GraphQL server compatible with Relay.&lt;br&gt;
Many developers avoid using Relay and instead use Apollo Client for complex applications, due to its simplicity and flexibility. It is hard to set up compared to other frameworks, but when everything is done, it is less error-prone and can be used in production serving a lot of users.&lt;br&gt;
The big advantage of React Relay is that it is supported by Facebook and is tested by millions of users on their social networks. In the new release of React18, the Suspense feature is deeply integrated with Relay. So, if you are using React for your application, with Relay you can get a great performance boost.&lt;/p&gt;

&lt;p&gt;From the official documentation:&lt;/p&gt;

&lt;p&gt;Relay is composed of three core parts:&lt;/p&gt;

&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Relay Compiler&lt;/em&gt;: A GraphQL to GraphQL optimizing compiler, providing general utilities for transforming and optimizing queries as well as generating build artifacts. A novel feature of the compiler is that it facilitates experimentation with new GraphQL features - in the form of custom directives - by making it easy to translate code using these directives into standard, spec-compliant GraphQL.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Relay Runtime&lt;/em&gt;: A full-featured, high-performance GraphQL runtime that can be used to build higher-level client APIs. The runtime features a normalized object cache, optimized "write" and "read" operations, a generic abstraction for incrementally fetching field data (such as for pagination), garbage collection for removing unreferenced cache entries, optimistic mutations with arbitrary logic, support for building subscriptions and live queries, and more.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;React/Relay&lt;/em&gt;: A high-level product API that integrates the Relay Runtime with React. This is the primary public interface to Relay for most product developers, featuring APIs to fetch the data for a query or define data dependencies for reusable components (e.g. useFragment).&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;Installation:&lt;br&gt;
For some reason, I have got an error when using the npm package manager. So I'm using yarn instead.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add relay-runtime react-relay
yarn add --dev relay-compiler babel-plugin-relay
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add schema.graphql to your project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd my-project
curl https://raw.githubusercontent.com/ogurenko/graphql-api/main/schema.graphql &amp;gt; schema.graphql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Modify package.json to run relay compiler:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"scripts": {
 "start": "yarn run relay &amp;amp;&amp;amp; react-scripts start",
 "build": "yarn run relay &amp;amp;&amp;amp; react-scripts build",
 "relay": "yarn run relay-compiler"
 },
 "relay": {
 "src": "./src/",
 "schema": "./schema.graphql"
 },
 ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can run the app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see your app running.&lt;br&gt;
Now it is time to configure the Relay environment. Create a file called RelayEnvironment.js in src/ and add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Environment, Network, RecordSource, Store } from "relay-runtime";
import FetchedData from "./FetchData";


export default new Environment({
 network: Network.create(() =&amp;gt; FetchedData()),
 store: new Store(new RecordSource()),
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add FetchData.js to src/ and add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;async function FetchedData() {

 const response = await fetch("https://countries.trevorblades.com/", {
 method: "POST",
 headers: {
 "Content-Type": "application/json",
 },
 body: JSON.stringify({
 query: "{countries { name }}",
 }),
 });

 return await response.json();
}

export default FetchedData;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace the contents of src/App.js with the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from "react";
import graphql from "babel-plugin-relay/macro";
import {
 RelayEnvironmentProvider,
 loadQuery,
 usePreloadedQuery,
} from "react-relay/hooks";
import RelayEnvironment from "./RelayEnvironment";

const { Suspense } = React;


const countriesQuery = graphql`
 query AppCountryNamesQuery {
 countries {
 name
 }
 }
`;


const preloadedQuery = loadQuery(RelayEnvironment, countriesQuery, {
 /* query variables */
});

function App(props) {
 const data = usePreloadedQuery(countriesQuery, props.preloadedQuery);
console.log(data.countries);
 const countriesName = [];
 data.countries.map((c) =&amp;gt; countriesName.push(c.name));
 return (
 &amp;lt;div className="App"&amp;gt;
 &amp;lt;header className="App-header"&amp;gt;
 {countriesName?.map((c, index) =&amp;gt; &amp;lt;ul key={index}&amp;gt;{c}&amp;lt;/ul&amp;gt;)}
 &amp;lt;/header&amp;gt;
 &amp;lt;/div&amp;gt;
 );
}

function AppRoot() {
 return (
 &amp;lt;RelayEnvironmentProvider environment={RelayEnvironment}&amp;gt;
 &amp;lt;Suspense fallback={"Loading..."}&amp;gt;
 &amp;lt;App preloadedQuery={preloadedQuery} /&amp;gt;
 &amp;lt;/Suspense&amp;gt;
 &amp;lt;/RelayEnvironmentProvider&amp;gt;
 );
}

export default AppRoot;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Modify src/index.js to run the app with the latest version of React:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from "react";
import { createRoot } from "react-dom/client";
import App from "./App";

const root = createRoot(document.getElementById("root"));

root.render(
 &amp;lt;React.StrictMode&amp;gt;
 &amp;lt;App /&amp;gt;
 &amp;lt;/React.StrictMode&amp;gt;
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You're done!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; To find out more about the environment and particular hooks in the Relay system, please refer to the &lt;a href="https://relay.dev/docs/api-reference/relay-environment-provider/"&gt;official documentation&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Apollo Client
&lt;/h2&gt;

&lt;p&gt;At the end of this comprehensive guide, you will learn how to use Apollo Client to fetch data from a GraphQL server.&lt;br&gt;
Apollo is a gold standard between the GraphQL ecosystem and React. It's simple, powerful, and flexible. It has a lot of features for modern applications. The downside is the bigger size of the library. It is not convenient to use this "mega" library for a simple application.&lt;br&gt;
Apollo is a platform-agnostic client. It can be used with any framework on the client-side, as well as with vanilla JavaScript. Works well with TypeScript and serverless architectures. Works well with Node.js and supports many libraries.&lt;/p&gt;

&lt;p&gt;Installation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install @apollo/client graphql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a client:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;App.js:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react'
import { ApolloProvider, ApolloClient, InMemoryCache } from "@apollo/client";
import { FetchedData } from "./FetchData";

const client = new ApolloClient({
 uri: "https://countries.trevorblades.com",
 cache: new InMemoryCache()
});

export default function App() {
 return (
 &amp;lt;ApolloProvider client={client}&amp;gt;
 &amp;lt;FetchedData /&amp;gt;
 &amp;lt;/ApolloProvider&amp;gt;
 );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;FetchData.js:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from "react";
import { useQuery, gql } from "@apollo/client";

const countriesQuery = gql`
 query {
 countries {
 name
 }
 }
`;

export const FetchedData = () =&amp;gt; {
 const { loading, error, data } = useQuery(countriesQuery);

 if (loading) return &amp;lt;p&amp;gt;Loading ... &amp;lt;/p&amp;gt;;
 if (error) return &amp;lt;p&amp;gt;Erorr ... &amp;lt;/p&amp;gt;;

 const countriesList = data.countries.map((country, index) =&amp;gt; (
 &amp;lt;ul key={index}&amp;gt;{country.name}&amp;lt;/ul&amp;gt;
 ));
 return (
 &amp;lt;&amp;gt;
 &amp;lt;h1&amp;gt;Countries&amp;lt;/h1&amp;gt;
 {countriesList}
 &amp;lt;/&amp;gt;
 );
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Start the app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, Apollo Client leverages the power of React Context and Hooks. Additionally resolves the problems with caching, state management, and error handling.&lt;/p&gt;

&lt;p&gt;Bundle size and popularity of the GraphQL clients:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href="https://github.com/prisma-labs/graphql-request"&gt;graphql-request&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href="https://github.com/nearform/graphql-hooks"&gt;graphql-hooks&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href="https://formidable.com/open-source/urql/"&gt;urql&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href="https://relay.dev/"&gt;React-Relay&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href="https://www.apollographql.com/docs/react/get-started/"&gt;apollo-client&lt;/a&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Size&lt;/td&gt;
&lt;td&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--I4V9PyeV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://badgen.net/bundlephobia/minzip/graphql-request%3F%26label%3D" alt="" width="" height=""&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--N56rTFdt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://badgen.net/bundlephobia/minzip/graphql-hooks%3Fcolor%3Dgreen%26label%3D" alt="" width="49" height="20"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9yEGGjNi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://badgen.net/bundlephobia/minzip/urql%3Flabel%3D" alt="" width="49" height="20"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xMsV846B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://badgen.net/bundlephobia/minzip/react-relay%3Fcolor%3Dred%26label%3D" alt="" width="56" height="20"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5_6dRrLP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://badgen.net/bundlephobia/minzip/%40apollo/client%3Flabel%3D" alt="" width="56" height="20"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Stars&lt;/td&gt;
&lt;td&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tsQwjyHR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://badgen.net/github/stars/prisma-labs/graphql-request%3Flabel%3D" alt="" width="37" height="20"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lgeDbnDz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://badgen.net/github/stars/nearform/graphql-hooks%3Flabel%3D%26color%3Dred" alt="" width="37" height="20"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UtC8yrvg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://badgen.net/github/stars/FormidableLabs/urql%3Flabel%3D" alt="" width="37" height="20"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9bh46hnL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://badgen.net/github/stars/facebook/relay%3Flabel%3D" alt="" width="44" height="20"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--14_XcUn4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://badgen.net/github/stars/apollographql/apollo-client%3Flabel%3D%26color%3Dgreen" alt="" width="44" height="20"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Forks&lt;/td&gt;
&lt;td&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FdyFHbr6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://badgen.net/github/forks/prisma-labs/graphql-request%3Flabel%3D" alt="" width="33" height="20"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_584lVnz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://badgen.net/github/forks/nearform/graphql-hooks%3Flabel%3D%26color%3Dred" alt="" width="26" height="20"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DxumZVPp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://badgen.net/github/forks/FormidableLabs/urql%3Flabel%3D" alt="" width="33" height="20"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--F-4EM_V9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://badgen.net/github/forks/facebook/relay%3Flabel%3D" alt="" width="37" height="20"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VuWjqpwE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://badgen.net/github/forks/apollographql/apollo-client%3Flabel%3D%26color%3Dgreen" alt="" width="37" height="20"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Issues&lt;/td&gt;
&lt;td&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rBvW4iYc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://badgen.net/github/issues/prisma-labs/graphql-request%3Flabel%3D" alt="" width="33" height="20"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RS_Mb2MC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://badgen.net/github/issues/nearform/graphql-hooks%3Flabel%3D%26color%3Dgreen" alt="" width="33" height="20"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--h3ty10Yu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://badgen.net/github/issues/FormidableLabs/urql%3Flabel%3D" alt="" width="33" height="20"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ABF_Un-B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://badgen.net/github/issues/facebook/relay%3Flabel%3D" alt="" width="37" height="20"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vF3UHbbn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://badgen.net/github/issues/apollographql/apollo-client%3Flabel%3D%26color%3Dred" alt="" width="37" height="20"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Downloads&lt;/td&gt;
&lt;td&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GB4QVL5t--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://badgen.net/npm/dw/graphql-request%3Flabel%3D%26color%3Dgreen" alt="" width="73" height="20"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--88HvbB8a--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://badgen.net/npm/dw/graphql-hooks%3Flabel%3D%26color%3Dred" alt="" width="67" height="20"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lQPVQIRW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://badgen.net/npm/dw/urql%3Flabel%3D%26color%3Dblue" alt="" width="85" height="20"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--d_hmzGRw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://badgen.net/npm/dw/react-relay%3Flabel%3D%26color%3Dblue" alt="" width="85" height="20"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--o8LU2Bn2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://badgen.net/npm/dw/apollo-client%3Flabel%3D%26color%3Dblue" alt="" width="85" height="20"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;red flag&lt;/strong&gt;: the worst result among all the clients&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;green flag&lt;/strong&gt;: the best result among all the clients&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Size&lt;/strong&gt;: source &lt;em&gt;Bundlephobia&lt;/em&gt; (mini zipped size of the bundle)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stars &amp;amp; Issues &amp;amp; Forks&lt;/strong&gt;: source &lt;em&gt;Github&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Downloads&lt;/strong&gt;: source &lt;em&gt;NPM&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The table above shows that GraphQL-request and urql are overall the most balanced libraries. There are no extreme results in any of these two clients.&lt;br&gt;
Apollo-client is the most popular client in the community. On the other hand, it has the most issues.&lt;br&gt;
GraphQL-hooks is the least popular client in the community. That's not suggesting that is the bad solution for your application.&lt;br&gt;
GraphQL-request is the most downloaded client, so it speaks for itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Axios, React-Query, and SWR are great tools for any protocol and can be used to build a GraphQL client. My focus is on the protocol-specific GraphQL clients.&lt;br&gt;
The GraphQL clients presented in this post, are all pretty solid and have a lot of good features. You can find a lot of comparison tables and examples of how to use the GraphQL clients on the internet. But this post aims to show you practical examples, with the same query and different GraphQL clients. I think that the best way to learn is to try it out on the same workload and see how it works.&lt;/p&gt;

&lt;p&gt;Opinionated recommendations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;For the sake of simplicity, I recommend using &lt;strong&gt;graphql-request&lt;/strong&gt;. It is a simple, fast, and small library that is easy to use.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you need data on many pages, across different components, you can use &lt;strong&gt;graphql-hooks&lt;/strong&gt;, which uses React Context and Hooks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you are looking for a GraphQL client that is more powerful, I recommend using &lt;strong&gt;urql&lt;/strong&gt;. Although it is less popular than Apollo Client, it has a lot of good features. Great post about it: &lt;a href="https://javascript.plainenglish.io/how-i-switched-from-apollo-to-urql-in-my-next-js-site-and-why-it-was-worth-it-9c7394ec150d"&gt;I Switched From Apollo To Urql (And It Was Worth It)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you need an enterprise solution, you can use &lt;strong&gt;react-relay&lt;/strong&gt;. The learning curve is a bit more complex, but once you set up the environment, your app is less likely to break.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

&lt;p&gt;References:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.logrocket.com/5-graphql-clients-for-javascript-and-node-js/"&gt;5 GraphQL clients for JavaScript and Node.js&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.logrocket.com/axios-vs-fetch-best-http-requests/"&gt;Axios vs. fetch(): Which is best for making HTTP requests?&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://formidable.com/open-source/urql/docs/comparison/"&gt;Urql&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://react-query.tanstack.com/comparison"&gt;React-Query&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>graphql</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Comprehensive guide to GraphQL clients, part 2</title>
      <dc:creator>Drago</dc:creator>
      <pubDate>Tue, 12 Apr 2022 11:06:21 +0000</pubDate>
      <link>https://forem.com/drago/comprehensive-guide-to-graphql-clients-part-2-3o8f</link>
      <guid>https://forem.com/drago/comprehensive-guide-to-graphql-clients-part-2-3o8f</guid>
      <description>&lt;h2&gt;
  
  
  Urql
&lt;/h2&gt;

&lt;p&gt;The official repository says that Urql is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The highly customizable and versatile GraphQL client with which you add on features like normalized caching as you grow.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Urql is an advanced GraphlQL client which has options for caching, normalization, and more. In modern development, it is a must-have, especially if you are building a complex application.&lt;/p&gt;

&lt;p&gt;Installation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install urql graphql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;App.js:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react';
import FetchedData from './FetchData';
import { createClient, Provider } from 'urql';

const client = createClient({
 url: 'https://countries.trevorblades.com/',
});

export default function App() {
 return (
 &amp;lt;Provider value={client}&amp;gt;
 &amp;lt;FetchedData /&amp;gt;
 &amp;lt;/Provider&amp;gt;
 );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;FetchData.js:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from "react";
import { useQuery } from "urql";
const countriesQuery = `
query {
 countries {
 name
 }
}
`;

const FetchedData = () =&amp;gt; {
 const [result] = useQuery({ query: countriesQuery });

 const { data, fetching, error } = result;
 console.log(data);

 if (fetching) return &amp;lt;p&amp;gt;Loading...&amp;lt;/p&amp;gt;;
 if (error) return &amp;lt;p&amp;gt;Error: {error.message}&amp;lt;/p&amp;gt;;

 const countriesList = data.countries.map((country, i) =&amp;gt; (
 &amp;lt;ul key={i}&amp;gt;{country.name}&amp;lt;/ul&amp;gt;
 ));

 return (
 &amp;lt;div&amp;gt;
 &amp;lt;h1&amp;gt;Countries&amp;lt;/h1&amp;gt;
 {countriesList}
 &amp;lt;/div&amp;gt;
 );
};

export default FetchedData;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  SWR
&lt;/h2&gt;

&lt;p&gt;The simple and effective way to fetch data is to use the SWR library.&lt;/p&gt;

&lt;p&gt;Install SWR:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install swr
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First, you need to import the library and create a fetcher function. For using SWR with GraphQL, you create a custom fetcher function with libraries like graphql-request or graphql-hooks.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;FetchData.js:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { request } from "graphql-request";
import useSWR from "swr";

const FetchedData = () =&amp;gt; {
 const countriesQuery = `
 query {
 countries {
 name
 }
 }
 `;

 const url = "https://countries.trevorblades.com/";

 const fetcher = () =&amp;gt; request(url, countriesQuery);

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

 if (error) return &amp;lt;div&amp;gt;failed to load&amp;lt;/div&amp;gt;;
 if (!data) return &amp;lt;div&amp;gt;loading...&amp;lt;/div&amp;gt;;

 const countriesList = data?.countries.map((c, i) =&amp;gt; &amp;lt;ul key={i}&amp;gt;{c.name}&amp;lt;/ul&amp;gt;);

 return (
 &amp;lt;&amp;gt;
 &amp;lt;h1&amp;gt;Countries&amp;lt;/h1&amp;gt;
 {countriesList}
 &amp;lt;/&amp;gt;
 );
};

export default FetchedData;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;App.js:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import FetchedData from "./FetchData";

export default function App() {
return (
 &amp;lt;FetchedData /&amp;gt;
);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As simple as that. As you can see, using SWR with GraphQL is straightforward. You avoid the need to create a state management system, all logic is in the useSWR hook.&lt;/p&gt;

&lt;h2&gt;
  
  
  React Query
&lt;/h2&gt;

&lt;p&gt;As official documentation says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Because React Query's fetching mechanisms are agnostically built on Promises, you can use React Query with literally any asynchronous data fetching client, including GraphQL!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;React Query is very similar to SWR, but it is built on top of React Context and React Hooks.&lt;br&gt;
Install React Query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install react-query
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;FetchData.js:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { request } from "graphql-request";
import { useQuery } from "react-query";

const FetchedData = () =&amp;gt; {
 const countriesQuery = `
 query {
 countries {
 name
 }
 }
 `;

 const url = "https://countries.trevorblades.com/";

 const fetcher = () =&amp;gt; request(url, countriesQuery);

 const { isLoading, error, data } = useQuery(url, fetcher);

 if (error) return &amp;lt;div&amp;gt;failed to load&amp;lt;/div&amp;gt;;
 if (isLoading) return &amp;lt;div&amp;gt;loading...&amp;lt;/div&amp;gt;;

 const countriesList = data?.countries.map((c, i) =&amp;gt; &amp;lt;ul key={i}&amp;gt;{c.name}&amp;lt;/ul&amp;gt;);

 return (
 &amp;lt;&amp;gt;
 &amp;lt;h1&amp;gt;Countries&amp;lt;/h1&amp;gt;
 {countriesList}
 &amp;lt;/&amp;gt;
 );
};

export default FetchedData;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;App.js:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import FetchedData from "./FetchData";
import { QueryClient, QueryClientProvider } from "react-query";

const queryClient = new QueryClient();

export default function App() {
return (
 &amp;lt;QueryClientProvider client={queryClient}&amp;gt;
 &amp;lt;FetchedData /&amp;gt;
 &amp;lt;/QueryClientProvider&amp;gt;
);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hopefully, you'll find an "ideal" client for your app and that this post added positive thoughts in that manner.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>react</category>
      <category>graphql</category>
    </item>
    <item>
      <title>Comprehensive Guide to GraphQL Clients, part 1</title>
      <dc:creator>Drago</dc:creator>
      <pubDate>Sat, 09 Apr 2022 10:16:19 +0000</pubDate>
      <link>https://forem.com/drago/comprehensive-guide-to-graphql-clients-part-1-2372</link>
      <guid>https://forem.com/drago/comprehensive-guide-to-graphql-clients-part-1-2372</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;As you already know, GraphQL is a query language for APIs. It is a declarative language, which means that it is easy to write queries. However, it is also a flexible language, which means that it is easy to write queries that are not declarative. This guide will help you to write declarative queries. Until now, you have created a server that returns data. However, you have not used the data in any way. This guide will help you to use the data in a declarative way.&lt;br&gt;
GraphQL clients are used to sending queries to a GraphQL server. Requests are sent in the form of a query string. The response is returned in the form of a JSON object. The response is a JSON object that contains the data that is requested. A request is made to a GraphQL server using the HTTP protocol, so you can use the same client as a client for RESTful APIs.&lt;/p&gt;
&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;
&lt;h2&gt;
  
  
  GraphQL IDE's
&lt;/h2&gt;

&lt;p&gt;IDEs are test tools to check the correctness of your queries. You can define your queries in the IDE and then send them to the server. The server will return the data that is requested if the query is correct. There are a lot of IDEs available.&lt;br&gt;
The most popular and the simplest IDE for GraphQL queries is &lt;a href="https://github.com/graphql/graphiql"&gt;GraphiQL&lt;/a&gt;.&lt;br&gt;
The modern clone of GraphiQL is &lt;a href="https://www.electronjs.org/apps/graphql-playground"&gt;GraphQL Playground&lt;/a&gt;. The environment is cleaner and has some advanced features.&lt;br&gt;
The recent IDE for GraphQL queries is &lt;a href="https://studio.apollographql.com/"&gt;Apollo Explorer&lt;/a&gt;.&lt;br&gt;
All-around tools such as &lt;a href="https://www.getpostman.com/"&gt;Postman&lt;/a&gt; and &lt;a href="https://www.insomnia.rest/"&gt;Insomnia&lt;/a&gt; are great tools for testing either GraphQL queries or RESTful APIs.&lt;/p&gt;
&lt;h2&gt;
  
  
  Curl
&lt;/h2&gt;

&lt;p&gt;The tool for quickly sending queries to a GraphQL server is &lt;a href="https://curl.haxx.se/"&gt;curl&lt;/a&gt;. It is a command-line tool that allows you to send simple queries to a GraphQL server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl  -X POST -H "Content-Type: application/json" -d '{"query": "{countries { name }}"}' 'https://countries.trevorblades.com/'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is useful for debugging and quick testing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install ReactJS
&lt;/h2&gt;

&lt;p&gt;The first step is to install ReactJS as our library of choice for creating UI components.&lt;br&gt;
If you have not installed ReactJS, you can install it using the following command in the command line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx create-react-app my-app
cd my-app
npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you are ready to deep dive into the GraphQL world.&lt;/p&gt;

&lt;h2&gt;
  
  
  Native Fetch
&lt;/h2&gt;

&lt;p&gt;Fetch is a native built-in JavaScript client for making HTTP requests. Let's see how to use fetch to send a query to a GraphQL server.&lt;/p&gt;

&lt;p&gt;Create a file FetchData.js in the root of your project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useState, useEffect } from "react";

const FetchedData = () =&amp;gt; {
  const [country, setCountry] = useState();
  const fetchData = async (req, res) =&amp;gt; {
    try {
      const response = await fetch("https://countries.trevorblades.com/", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          query: "{countries { name }}",
        }),
      });
      const { data } = await response.json();

      const countriesName = [];
      data.countries.map((c) =&amp;gt; countriesName.push(c.name));
      setCountry(countriesName);
    } catch (error) {
      console.log(error);
    }
  };

  useEffect(() =&amp;gt; {
    fetchData();
  }, []);
  const countriesList = country?.map((c, index) =&amp;gt; &amp;lt;ul key={index}&amp;gt;{c}&amp;lt;/ul&amp;gt;);
  return (
    &amp;lt;&amp;gt;
      &amp;lt;h1&amp;gt;Countries&amp;lt;/h1&amp;gt;
      {countriesList}
    &amp;lt;/&amp;gt;
  );
};

export default FetchedData;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then in App.js, you can use the component FetchedData.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import FetchedData from "./FetchData";

export default function App() {
return &amp;lt;FetchedData /&amp;gt;;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Axios
&lt;/h2&gt;

&lt;p&gt;Axios is a JavaScript library for making HTTP requests. It is a wrapper around the XMLHttpRequest object. It's a promise-based HTTP client for the browser and node.js.&lt;br&gt;
Axios automatically parses JSON responses. It is a shorthand for fetch.&lt;br&gt;
Install Axios using the following command in the command line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install axios
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;FetchData.js
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useState, useEffect } from "react";
import axios from "axios";

const FetchedData = () =&amp;gt; {
  const [country, setCountry] = useState();
  const fetchData = async (req, res) =&amp;gt; {
    try {
      const response = await axios.post("https://countries.trevorblades.com/", {
        query: " {countries { name }}"
      });

      const { data } = response.data;

      const countriesName = [];
      data.countries.map((c) =&amp;gt; countriesName.push(c.name));
      setCountry(countriesName);
    } catch (error) {
      console.log(error);
    }
  };

  useEffect(() =&amp;gt; {
    fetchData();
  }, []);
  const countriesList = country?.map((c, index) =&amp;gt; &amp;lt;ul key={index}&amp;gt;{c}&amp;lt;/ul&amp;gt;);
  return (
    &amp;lt;&amp;gt;
      &amp;lt;h1&amp;gt;Countries&amp;lt;/h1&amp;gt;
      {countriesList}
    &amp;lt;/&amp;gt;
  );
};

export default FetchedData;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;App.js is the same as before.&lt;/p&gt;

&lt;h2&gt;
  
  
  graphql-request
&lt;/h2&gt;

&lt;p&gt;For simple requests, graphql-request is a good choice. This library is only '5.2kb' and it is one of the fastest and lightest GraphQL clients. It supports async/await, typescript, isomorphism, and works on both the client and server sides.&lt;/p&gt;

&lt;p&gt;Install graphql-request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install graphql-request graphql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, you need to import the library and create a client.&lt;br&gt;
If you are not familiar with the code in these examples, I recommend you to read the documentation about the fundamentals of React.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;FetchData.js
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useState, useEffect, useCallback } from "react";
import { request, gql } from "graphql-request";

const FetchedData = () =&amp;gt; {
  const [country, setCountry] = useState();

  const countriesQuery = gql`
    query {
      countries {
        name
      }
    }
  `;

  const url = "https://countries.trevorblades.com/";

  const fetchData = useCallback(async () =&amp;gt; {
    try {
      const response = await request(url, countriesQuery);

      const { countries } = response;

      const countryName = countries?.map((c, i) =&amp;gt; &amp;lt;ul key={i}&amp;gt;{c.name}&amp;lt;/ul&amp;gt;);
      setCountry(countryName);
    } catch (error) {
      console.log(error);
    }
  }, [countriesQuery]);

  useEffect(() =&amp;gt; {
    fetchData();
  }, [fetchData]);

  return (
    &amp;lt;&amp;gt;
      &amp;lt;h1&amp;gt;Countries&amp;lt;/h1&amp;gt;
      {country}
    &amp;lt;/&amp;gt;
  );
};

export default FetchedData;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;App.js is the same as in the previous example.&lt;/p&gt;
&lt;h2&gt;
  
  
  graphql-hooks
&lt;/h2&gt;

&lt;p&gt;Graphql-hooks is a library that allows you to use GraphQL clients in React. It is a promise-based library for the browser and node.js. Conceptually, it is similar to graphql-request, but the difference is that first is formed a client and then the whole app is wrapped in a context in which the client is available(wrapping app). Tiny bundle: only 7.6kB (2.8 gzipped)&lt;/p&gt;

&lt;p&gt;Install graphql-hooks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install graphql-hooks
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;App.js
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import FetchedData from "./FetchData";
import { GraphQLClient, ClientContext } from "graphql-hooks";

const client = new GraphQLClient({
  url: "https://countries.trevorblades.com/"
});

export default function App() {
  return (
      &amp;lt;ClientContext.Provider value={client}&amp;gt;
        &amp;lt;FetchedData /&amp;gt;
      &amp;lt;/ClientContext.Provider&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;FetchData.js
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useState, useEffect, useCallback } from "react";
import { useQuery } from "graphql-hooks";

const FetchedData = () =&amp;gt; {
  const [country, setCountry] = useState();

  const countriesQuery = `
    query {
      countries {
        name
      }
    }
  `;

  const { loading, error, data } = useQuery(countriesQuery);

  const fetchData = useCallback(async () =&amp;gt; {
    try {

      const { countries } = data;
      console.log(countries);


      const countryName = countries?.map((c, i) =&amp;gt; &amp;lt;ul key={i}&amp;gt;{c.name}&amp;lt;/ul&amp;gt;)
      setCountry(countryName);
    } catch (error) {
      console.log(error);
    }
  }, [data]);

  useEffect(() =&amp;gt; {
    fetchData();
  }, [fetchData]);

  if (loading) return &amp;lt;p&amp;gt;Loading...&amp;lt;/p&amp;gt;;
  if (error) return &amp;lt;p&amp;gt;Error: {error.message}&amp;lt;/p&amp;gt;;

  return (
    &amp;lt;&amp;gt;
      &amp;lt;h1&amp;gt;Countries&amp;lt;/h1&amp;gt;
      {country}
    &amp;lt;/&amp;gt;
  );
};

export default FetchedData;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you don't need advanced features, graphql-hooks is an ideal choice, because it is very functional and easy to use. It is also very lightweight. Even has a self-contained development environment in form of extension.&lt;/p&gt;

</description>
      <category>graphql</category>
      <category>react</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>GraphQL Subscription</title>
      <dc:creator>Drago</dc:creator>
      <pubDate>Sat, 08 Jan 2022 15:43:18 +0000</pubDate>
      <link>https://forem.com/drago/graphql-subscription-580p</link>
      <guid>https://forem.com/drago/graphql-subscription-580p</guid>
      <description>&lt;h3&gt;
  
  
  Introduction to GraphQL Subscription
&lt;/h3&gt;



&lt;p&gt;Finally, we will learn how to use GraphQL Subscription to get real-time updates from the server.&lt;br&gt;
The GraphQL Subscription is a way to get real-time updates from the server. It's used the WebSocket protocol, instead of HTTP, because it's more efficient, two-way communication. The server sends updates to the client, and the client sends updates to the server. &lt;strong&gt;Subscription&lt;/strong&gt; means that the client is not required to send a request to the server every time it wants to get an update. The connection between the client and the server is maintained by the server, using the WebSocket API protocol.&lt;br&gt;
For implementing GraphQL Subscription, we will use the &lt;a href="https://www.npmjs.com/package/subscriptions-transport-ws" rel="noopener noreferrer"&gt;subscription-transport-ws&lt;/a&gt; library.&lt;br&gt;
There are many examples in practical projects, but the most popular are: google maps, real-time flight tracking, autonomous vehicles, chat applications, vehicle location, seat reservations, ticket reservations, etc.&lt;br&gt;
  &lt;br&gt;&lt;br&gt;
  &lt;br&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Implementing GraphQL Subscription
&lt;/h2&gt;



&lt;p&gt;Create a new project and add the following dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install express express-graphql graphql-playground-middleware-express graphql-subscriptions subscriptions-transport-ws ws
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or use yarn:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add express express-graphql graphql-playground-middleware-express graphql-subscriptions subscriptions-transport-ws ws
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A useful tool for developing purposes is nodemon, which automatically restarts the server when the code changes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -D nodemon
// or
yarn add -D nodemon
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;h2&gt;
  
  
  Creating a server
&lt;/h2&gt;



&lt;p&gt;Creating a server begins with creating a new schema. The schema is a collection of GraphQL types, which are used to define the data that the server can return. Let's say we have a collection of posts, and we want to follow published posts in real-time, using GraphQL Subscription.&lt;/p&gt;



&lt;blockquote&gt;
&lt;p&gt;Note: To use ES6 syntax you must provide the "type" : "module" property in package.json.&lt;/p&gt;
&lt;/blockquote&gt;



&lt;h3&gt;
  
  
  Types
&lt;/h3&gt;



&lt;p&gt;Let's define the type of post. Create a folder called types in the root of the project. Create a file called &lt;code&gt;post.js&lt;/code&gt; in the &lt;code&gt;types&lt;/code&gt; folder.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;post.js
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import {
  GraphQLID,
  GraphQLNonNull,
  GraphQLObjectType,
  GraphQLString,
} from "graphql";

export const PostType = new GraphQLObjectType({
  name: "Post",
  fields: () =&amp;gt; ({
    id: {
      type: new GraphQLNonNull(GraphQLID),
    },
    title: {
      type: new GraphQLNonNull(GraphQLString),
    },
    content: {
      type: new GraphQLNonNull(GraphQLString),
    },
  }),
});


export const PostSubscription = new GraphQLObjectType({
  name: "PostSubscription",
  fields: () =&amp;gt; ({
    id: {type: new GraphQLNonNull(GraphQLID)},
    title: {type: new GraphQLNonNull(GraphQLString)},
    content: {type: new GraphQLNonNull(GraphQLString)},
  }),
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's define a query type, which is used to get the post, in the same folder.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;query.js
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import {
  GraphQLID,
  GraphQLObjectType,
  GraphQLList,
} from "graphql";
import { PostType } from "./post.js";
import { getPost, getPosts } from "../resolvers/resolvers.js";


const Query = new GraphQLObjectType({
  name: "Query",
  fields: () =&amp;gt; ({
    post: {
      type: PostType,
      args: {
        id: {
          type: GraphQLID,
        },
      },
      resolve: (parent, args) =&amp;gt; getPost(args.id),
    },
    posts: {
      type: new GraphQLList(PostType),
      resolve: () =&amp;gt; getPosts(),
    },
  }),
});


export default Query;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We defined the PostType and the Query type. The PostType is used to define the data that the server can return. The Query type is used to define the data that the client can request. Also, we defined the PostSubscription type, which is used to define the data that the client can subscribe to. The resolvers are defined in the resolvers.js file, for better usability and separation of concerns.&lt;/p&gt;

&lt;p&gt;Let's create a mutation type, which is used to create, update and delete a new post, in the same folder.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;mutation.js
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import {
  GraphQLID,
  GraphQLNonNull,
  GraphQLObjectType,
} from "graphql";
import { addPost, updatePost, deletePost } from "../resolvers/resolvers.js";
import { PostType } from "./post.js";
import { InputPostType } from "./inputPost.js";


const Mutation = new GraphQLObjectType({
  name: "Mutation",
  fields: () =&amp;gt; ({
    addPost: {
      type: new GraphQLNonNull(PostType),
      args: {
        input: {
          type: new GraphQLNonNull(InputPostType),
        },
      },
      resolve: async (parent, args, {pubsub}) =&amp;gt; {
          const {title, content} = args.input;

          return addPost(title, content, pubsub);
      }
    },
    updatePost: {
      type: PostType,
      args: {
        input: {
          type: new GraphQLNonNull(InputPostType),
        },
      },
      resolve: async (parent, , {pubsub}) =&amp;gt; {
            const {id, title, content} = args.input;

            return updatePost(id, title, content, pubsub);
      },
    },
    deletePost: {
      type: new GraphQLNonNull(PostType),
      args: {
        id: {
          type: new GraphQLNonNull(GraphQLID),
        },
      },
      resolve: (parent, args, {pubsub}) =&amp;gt; {
          const { id } = args;
          return deletePost(id, pubsub);
      },
    },
  }),
});


export default Mutation;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Arguments are defined in the InputPost type. The InputPost is used to define the data that the client can send to the server. Arguably, the InputPost is not necessary, but it's good practice to define the data that the client can send to the server.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;inputPost.js
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import {
  GraphQLID,
  GraphQLNonNull,
  GraphQLInputObjectType,
  GraphQLString,
} from "graphql";


export const InputPostType = new GraphQLInputObjectType({
  name: "InputPost",
  fields: () =&amp;gt; ({
    id: {
      type: new GraphQLNonNull(GraphQLID),
    },
    title: {
      type: new GraphQLNonNull(GraphQLString),
    },
    content: {
      type: new GraphQLNonNull(GraphQLString),
    },
  }),
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And finally, we can create a subscription type, which is used to subscribe to the post.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;subscription.js
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { GraphQLNonNull, GraphQLObjectType } from "graphql";
import { PostSubscription } from "./post.js";


const Subscription = new GraphQLObjectType({
  name: "Subscription",
  fields: () =&amp;gt; ({
    post_added: {
      type: new GraphQLNonNull(PostSubscription),
      subscribe: (parent, args, {pubsub}) =&amp;gt; pubsub.asyncIterator("NEW_POST"),
      },
    post_updated: {
        type: new GraphQLNonNull(PostSubscription),
        subscribe: (parent, args, {pubsub}) =&amp;gt; pubsub.asyncIterator("POST_UPDATED"),
      },
    post_deleted: {
            type: new GraphQLNonNull(PostSubscription),
            subscribe: (parent, args, {pubsub}) =&amp;gt; pubsub.asyncIterator("POST_DELETED"),
        },
    },
  }),
});


export default Subscription;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;h3&gt;
  
  
  Resolvers
&lt;/h3&gt;



&lt;p&gt;Resolvers are defined in the resolvers.js file.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;resolvers.js
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { posts } from "../data/posts.js";

// Queries
export const getPosts = () =&amp;gt; posts;

export const getPost = (id) =&amp;gt; {
  if (id &amp;lt; posts.length) {
    return posts[id - 1];
  }
};


// Mutations
export const addPost = async (title, content, pubsub) =&amp;gt; {
  const id = posts.length + 1;
  const newPost = {id, title, content};
  posts.push(newPost);
  await pubsub.publish("NEW_POST", {post_added: newPost});
  return newPost;
};

export const updatePost = async (id, title, content, pubsub) =&amp;gt; {
  const post = posts.find(post =&amp;gt; post.id === parseInt(id));

  if (post) {
    post.title = title;
    post.content = content;
  }
  await pubsub.publish("POST_UPDATED", {post_updated: post});
  return post;
};


export const deletePost = async (id, pubsub) =&amp;gt; {
  const post = posts.find(post =&amp;gt; post.id === parseInt(id));

  if (!post) {
      throw new Error("Post not found");
  }
    posts.splice(posts.indexOf(post), 1);

  await pubsub.publish("POST_DELETED", {post_deleted: post});
  return post;
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Data is defined in the data.js file. You can find the data in the Github repository.&lt;br&gt;
Pubsub is a feature that publishes events to which clients can subscribe. Each of these events has a name, which is used to subscribe to the event (NEW_POST, POST_UPDATED, POST_DELETED). Based on the name, the asyncIterator method of the pubsub object is called and sends the event to the client. In the end, it remains to create a server to implement the subscription.&lt;/p&gt;



&lt;h3&gt;
  
  
  Server
&lt;/h3&gt;



&lt;ul&gt;
&lt;li&gt;index.js
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { GraphQLSchema, execute, subscribe } from "graphql";
import { WebSocketServer } from "ws";
import express from "express";
import { graphqlHTTP } from "express-graphql";
import { PubSub } from "graphql-subscriptions";
import Query from "./types/query.js";
import Mutation from "./types/mutation.js";
import Subscription from "./types/subscription.js";
import expressPlayground from "graphql-playground-middleware-express";
import { SubscriptionServer } from "subscriptions-transport-ws";

const app = express();
const pubsub = new PubSub();
const graphQLPlayground = expressPlayground.default;

// define the GraphQL schema
const schema = new GraphQLSchema({
  query: Query,
  mutation: Mutation,
  subscription: Subscription,
});


ap.use("/graphql", graphqlHTTP({
  schema,
  context: { pubsub },
}));

app.use("/playground", graphQLPlayground({
  endpoint: "/graphql",
  subscriptionEndpoint: `/graphql`,
}));


const server = app.listen(4000, () =&amp;gt; {

const wss = new WebSocketServer({
    server,
    path: "/graphql",
});

SubscriptionServer.create(
    {
        schema,
        execute,
        subscribe,
        onConnect: () =&amp;gt; {
           return { pubsub }
        },
    },
    wss,
);



  console.log("Server is running on http://localhost:4000");
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, open the browser and go to &lt;a href="http://localhost:4000/playground" rel="noopener noreferrer"&gt;http://localhost:4000/playground&lt;/a&gt;. Enter the fields relevant to the Subscription type and click on the Run button. Event listening will be started.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdragardelo%2Fimage%2Fupload%2Fv1640002054%2Fblog%2FSubscription_cup8uu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdragardelo%2Fimage%2Fupload%2Fv1640002054%2Fblog%2FSubscription_cup8uu.png" alt="Subscription"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, open another tab and create a post. The post will be added to the list of posts. the event will be published and should appear in the Subscription tab. This way, you can listen to the update and delete events, as well as the creation of a new post.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdragardelo%2Fimage%2Fupload%2Fv1640010441%2Fblog%2FSubscription_2_elmimj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdragardelo%2Fimage%2Fupload%2Fv1640010441%2Fblog%2FSubscription_2_elmimj.png" alt="Subscription_2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The complete code can be seen in the Github repository &lt;a href="https://github.com/ogurenko/graphql-api-subscription" rel="noopener noreferrer"&gt;Link&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>graphql</category>
      <category>beginners</category>
      <category>node</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
