Comparing hooks libraries for GraphQL
Tags: apollo, graphql, react
Published: 2020-04-17 18:18:18

---
title: Comparing hooks libraries for GraphQL
published: true
date: 2020-03-24 17:30:30 UTC
tags: apollo,graphql,react
canonical_url: https://blog.logrocket.com/comparing-hooks-libraries-for-graphql/
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/esum9rd42teu04y6xouu.png
---
**Written by [Ganesh Mani](https://blog.logrocket.com/author/ganeshmani/)**✏️

React Hooks are stateful functions that are used to maintain the state in a functional component. Basically, they break down complex React components by splitting them into smaller functional blocks.

The main problem with React class components is the need to maintain lots of abstractions, such as higher-order components (HOCs) and render props. React Hooks maintain the logic as a function, eliminating the need to encapsulate it.

Take a look at the following example.

{% codesandbox rmo8wkp1kn %}

GraphQL is a data query language that fetches only the data it needs rather than fetching all the data from the API. It has two operations: [queries](https://dev.to/bnevilleoneill/graphql-queries-explained-in-simple-terms-4inc) and [mutations](https://dev.to/bnevilleoneill/robust-graphql-mutations-the-relay-way-1o72). For real-time data, GraphQL uses a concept called [subscriptions](https://dev.to/bnevilleoneill/graphql-subscriptions-with-node-js-4m9i).

There are two major React Books libraries: [graphql-hooks](https://github.com/nearform/graphql-hooks) and [apollo/react-hooks](https://www.apollographql.com/docs/react/api/react-hooks/). To help you determine which library is best for your next GraphQL project, let’s compare them, examine their features, and weigh the pros and cons.

[![LogRocket Free Trial Banner](https://i0.wp.com/blog.logrocket.com/wp-content/uploads/2017/03/f760c-1gpjapknnuyhu8esa3z0jga.png?resize=1200%2C280&ssl=1)](https://logrocket.com/signup/)

## Project scenario

We’ll spin up a quick project to facilitate our comparison. Let’s implement a chat application that enables the user to log in and send group messages.

![Chat App Built With GraphQL Hooks](https://i0.wp.com/blog.logrocket.com/wp-content/uploads/2020/03/chat-app-built-with-graphql-hooks-1.gif?resize=720%2C450&ssl=1)

### **Backend setup**

I won’t spend too much time on the backend, but here’s a quick glimpse at how I set it up for this application:

![Backend of Chat App](https://i1.wp.com/blog.logrocket.com/wp-content/uploads/2020/03/backend-of-chat-app.png?resize=451%2C136&ssl=1)

Basically, I used [Hasura](https://dev.to/bnevilleoneill/building-a-product-hunt-clone-app-using-hasura-and-next-js-l9g) to set up GraphQL and a [Postgres database](https://dev.to/bnevilleoneill/getting-started-with-postgres-in-your-react-app-275b-temp-slug-9504682). This easy-to-use tool enables you to create a backend in minutes.

Out backend contains two tables:

- User, which includes information about the users
- Message, which stores all the users’ messages

The backend URL is [https://hasura-infiite-loader.herokuapp.com/v1alpha1/graphql](https://hasura-infiite-loader.herokuapp.com/v1alpha1/graphql); the WebSocket URL is ws://hasura-infiite-loader.herokuapp.com/v1alpha1/graphql.

## Apollo and React Hooks

To implement our app using Apollo, React Hooks, and React, we must first set up a React project using the following command.

```jsx
npx create-react-app apollo-react-hook-example
```

After that, install all the dependencies of the `@apollo/react-hooks` package.

```jsx
npm install @apollo/react-hooks apollo-client apollo-link-http apollo-link-ws apollo-link apollo-utilities apollo-cache-inmemory subscriptions-transport-ws
```

That’s a lot of packages! Let’s break them down one by one.

- [`@apollo/react-hooks`](https://www.apollographql.com/docs/react/api/react-hooks/) provides all the React Hooks required to use GraphQL with `apollo-client`. It contains `useQuery`, `useMutation`, and `useSubscription` to execute all the GraphQL operations
- [`apollo-client`](https://github.com/apollographql/apollo-client) provides all the packages you need to run the caching operations on the client side. It is often used with [`apollo-link-http`](https://www.apollographql.com/docs/link/links/http/) and [`apollo-cache-memory`](https://www.apollographql.com/docs/react/caching/cache-configuration/)
- [`apollo-link-http`](https://www.apollographql.com/docs/link/links/http/) is a chainable unit of operation that you can apply to your GraphQL request. It executes the unit one after another. Here we use an HTTP link to execute the GraphQL HTTP request
- [`apollo-link-ws`](https://www.apollographql.com/docs/link/links/ws/) creates a WebSocket link for the GraphQL client
- [`apollo-link`](https://www.apollographql.com/docs/link/#usage) the two functionalities described above fall under [`apollo-link`](https://www.apollographql.com/docs/link/#usage)
- [`apollo-utilities`](https://www.npmjs.com/package/apollo-utilities) provides utility functions for `apollo-client`
- [`apollo-cache-inmemory`](https://www.npmjs.com/package/apollo-cache-inmemory) provides caching functionalities for GraphQL requests
- [`subscription-transport-ws`](https://github.com/apollographql/subscriptions-transport-ws) is used with `apollo-link-ws` to facilitate GraphQL subscriptions

Now it’s time to set up `@apollo/react-hooks` with our application. Import all the packages into `App.js` .

```jsx
import ApolloClient from "apollo-client";
import { ApolloProvider } from "@apollo/react-hooks";
import { WebSocketLink } from "apollo-link-ws";
import { HttpLink } from "apollo-link-http";
import { split } from "apollo-link";
import { getMainDefinition } from "apollo-utilities";
import { InMemoryCache } from "apollo-cache-inmemory";
```

Set up the HTTP and WebSocket links with the server.

```jsx
const httpLink = new HttpLink({
  uri: "https://hasura-infiite-loader.herokuapp.com/v1alpha1/graphql" // use https for secure endpoint
});
// Create a WebSocket link:
const wsLink = new WebSocketLink({
  uri: "ws://hasura-infiite-loader.herokuapp.com/v1alpha1/graphql", // use wss for a secure endpoint
  options: {
    reconnect: true
  }
});
```

Once we have `httpLink` and `wsLink`, we need to split the request links so we can send different data to each link.

```jsx
// using the ability to split links, you can send data to each link
// depending on what kind of operation is being sent
const link = split(
  // split based on operation type
  ({ query }) => {
    const { kind, operation } = getMainDefinition(query);
    return kind === "OperationDefinition" && operation === "subscription";
  },
  wsLink,
  httpLink
);
```

Let’s create the Apollo client and configure it to Apollo Provider

```jsx
// Instantiate client
const client = new ApolloClient({
  link,
  cache: new InMemoryCache()
});

function App() {
  return (
    <ApolloProvider client={client}>
      <ThemeProvider theme={customTheme}>
        <div className="App">
          <Routes />
        </div>
      </ThemeProvider>
    </ApolloProvider>
  );
}
```

Complete the source code for `App.js`.

```jsx
import React from "react";
import logo from "./logo.svg";
import "./App.css";
import customTheme from "./theme";
import { ThemeProvider } from "@chakra-ui/core";
import Routes from "./routes";
import ApolloClient from "apollo-client";
import { ApolloProvider } from "@apollo/react-hooks";
import { WebSocketLink } from "apollo-link-ws";
import { HttpLink } from "apollo-link-http";
import { split } from "apollo-link";
import { getMainDefinition } from "apollo-utilities";
import { InMemoryCache } from "apollo-cache-inmemory";
const httpLink = new HttpLink({
  uri: "https://hasura-infiite-loader.herokuapp.com/v1alpha1/graphql" // use https for secure endpoint
});
// Create a WebSocket link:
const wsLink = new WebSocketLink({
  uri: "ws://hasura-infiite-loader.herokuapp.com/v1alpha1/graphql", // use wss for a secure endpoint
  options: {
    reconnect: true
  }
});
// using the ability to split links, you can send data to each link
// depending on what kind of operation is being sent
const link = split(
  // split based on operation type
  ({ query }) => {
    const { kind, operation } = getMainDefinition(query);
    return kind === "OperationDefinition" && operation === "subscription";
  },
  wsLink,
  httpLink
);
// Instantiate client
const client = new ApolloClient({
  link,
  cache: new InMemoryCache()
});
function App() {
  return (
    <ApolloProvider client={client}>
      <ThemeProvider theme={customTheme}>
        <div className="App">
          <Routes />
        </div>
      </ThemeProvider>
    </ApolloProvider>
  );
}
export default App;
```

Now we’ll create `Routes.js` for our application.

```jsx
import React from "react";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import LoginComponent from "./components/login";
import Chat from "./components/Chat";
const Routes = () => (
  <Router>
    <Route exact path="/" component={LoginComponent} />
    <Route path="/chat" component={Chat} />
  </Router>
);
export default Routes;
```

We have three main components:

1. Login
2. Chat
3. Chat item

![Chat App Components — Apollo](https://i2.wp.com/blog.logrocket.com/wp-content/uploads/2020/03/chat-app-components-apollo.png?resize=330%2C390&ssl=1)

Let’s examine these in more detail.

### Login component

Functionality for the login component is pretty simple. Our app will have a form where for the user to enter a name and password.

The GraphQL operation we need here is mutation. We’ll use a React Hook called `useMutation`. We’ll also use [`react-hook-form`](https://github.com/react-hook-form/react-hook-form) for form validation and [`chakraUI`](https://chakra-ui.com/) for UI.

```jsx
import { useMutation } from "@apollo/react-hooks";

import gql from "graphql-tag";
const LOGIN_USER = gql`
  mutation InsertUsers($name: String!, $password: String!) {
    insert_users(objects: { name: $name, password: $password }) {
      returning {
        id
        name
      }
    }
  }
`;
```

We have a mutation GraphQL operation that takes `name` and `password` as parameters and executes the `insert_users` mutation.

Next, define the `useMutation` hooks inside the login component with mutation GraphQL.

```jsx
 const [insert_users, { data }] = useMutation(LOGIN_USER);
```

Here is the complete source code for `Login`/`index.js`:

```jsx
import React, { useState, useEffect } from "react";
import { useForm } from "react-hook-form";
import {
  FormErrorMessage,
  FormLabel,
  FormControl,
  Input,
  Button,
  Box
} from "@chakra-ui/core";
import { useMutation } from "@apollo/react-hooks";
import gql from "graphql-tag";
const LOGIN_USER = gql`
  mutation InsertUsers($name: String!, $password: String!) {
    insert_users(objects: { name: $name, password: $password }) {
      returning {
        id
        name
      }
    }
  }
`;
const Login = ({ history }) => {
  const [state, setState] = useState({
    name: "",
    password: ""
  });
  const [insert_users, { data }] = useMutation(LOGIN_USER);
  useEffect(() => {
    const user = data && data.insert_users.returning[0];
    if (user) {
      localStorage.setItem("user", JSON.stringify(user));
      history.push("/chat");
    }
  }, [data]);
  const { handleSubmit, errors, register, formState } = useForm();
  function validateName(value) {
    let error;
    if (!value) {
      error = "Name is required";
    }
    return error || true;
  }
  function validatePassword(value) {
    let error;
    if (value.length <= 4) {
      error = "Password should be 6 digit long";
    }
    return error || true;
  }
  const onInputChange = e => {
    setState({ ...state, [e.target.name]: e.target.value });
  };
  const onSubmit = () => {
    insert_users({ variables: { name: state.name, password: state.password } });
    setState({ name: "", password: "" });
  };
  return (
    <Box>
      <form onSubmit={handleSubmit(onSubmit)}>
        <FormControl isInvalid={errors.name}>
          <FormLabel htmlFor="name">Name</FormLabel>
          <Input
            name="name"
            placeholder="name"
            onChange={onInputChange}
            ref={register({ validate: validateName })}
          />
          <FormErrorMessage>
            {errors.name && errors.name.message}
          </FormErrorMessage>
        </FormControl>
        <FormControl isInvalid={errors.password}>
          <FormLabel htmlFor="name">Password</FormLabel>
          <Input
            name="password"
            type="password"
            placeholder="password"
            onChange={onInputChange}
            ref={register({ validate: validatePassword })}
          />
          <FormErrorMessage>
            {errors.password && errors.password.message}
          </FormErrorMessage>
        </FormControl>
        <Button
          mt={4}
          variantColor="teal"
          isLoading={formState.isSubmitting}
          type="submit"
        >
          Submit
        </Button>
      </form>
    </Box>
  );
};
export default Login;
```

### Chat component

The chat component will primarily use two GraphQL operations: mutation and subscription. Since our chat app is a real-time application, we need to subscribe to get the updated data.

For that, we need the `useSubscription` React Hook to subscribe and the `useMutation` Hook to make the HTTP POST request on GraphQL.

```jsx
import { useMutation, useSubscription } from "@apollo/react-hooks";
import gql from "graphql-tag";
const MESSAGES_SUBSCRIPTION = gql`
  subscription {
    messages {
      id
      text
      users {
        id
        name
      }
    }
  }
`;
const SUBMIT_MESSAGES = gql`
  mutation InsertMessages($text: String!, $userid: Int!) {
    insert_messages(objects: { text: $text, created_user: $userid }) {
      returning {
        text
        created_user
        users {
          name
          id
        }
        id
      }
    }
  }
`;
```

`MESSAGES_SUBSCRIPTION` is a subscription GraphQL schema definition. `SUBMIT_MESSAGES` is a mutation GraphQL schema definition.

We’ll use both in our chat component.

```jsx
const [insert_messages, { returnData }] = useMutation(SUBMIT_MESSAGES);


const { loading, error, data: { messages } = [] } = useSubscription(
    MESSAGES_SUBSCRIPTION
  );
```

Messages from `useSubscription` will return updated data whenever there is a change in messages from GraphQL.

Here is the complete source code for `Chat`/`index.js`:

```jsx
import React, { useState, useEffect } from "react";
import { Box, Flex, Input } from "@chakra-ui/core";
import ChatItem from "../ChatItem";
import { useMutation, useSubscription } from "@apollo/react-hooks";
import gql from "graphql-tag";
const MESSAGES_SUBSCRIPTION = gql`
  subscription {
    messages {
      id
      text
      users {
        id
        name
      }
    }
  }
`;
const SUBMIT_MESSAGES = gql`
  mutation InsertMessages($text: String!, $userid: Int!) {
    insert_messages(objects: { text: $text, created_user: $userid }) {
      returning {
        text
        created_user
        users {
          name
          id
        }
        id
      }
    }
  }
`;
const Chat = () => {
  const [state, setState] = useState({
    text: ""
  });
  const [insert_messages, { returnData }] = useMutation(SUBMIT_MESSAGES);
  const { loading, error, data: { messages } = [] } = useSubscription(
    MESSAGES_SUBSCRIPTION
  );
  const onInputChage = e => {
    setState({ [e.target.name]: e.target.value });
  };
  const onEnter = e => {
    if (e.key === "Enter") {
      let user = localStorage.getItem("user");
      user = JSON.parse(user);
      insert_messages({ variables: { text: state.text, userid: user.id } });
      setState({ text: "" });
    }
  };
  return (
    <Box h="100vh" w="40%" margin="auto">
      <Flex direction="column" h="100%">
        <Box bg="blue" h="90%" w="100%" border="solid 1px" overflowY="scroll">
          {messages &&
            messages.map(message => {
              return <ChatItem item={message} />;
            })}
        </Box>
        <Box bg="green" h="10%" w="100%">
          <Input
            placeholder="Enter a message"
            name="text"
            value={state.text}
            onChange={onInputChage}
            onKeyDown={onEnter}
            size="md"
          />
        </Box>
      </Flex>
    </Box>
  );
};
export default Chat;
```

`ChatItem`/`index.js`:

```jsx
import React from "react";
import { Box, Flex, Avatar, Heading, Text } from "@chakra-ui/core";
const ChatItem = ({ item }) => {
  return (
    <Box h="60px">
      <Flex direction="row" alignItems="center" height="100%">
        <Avatar size="sm" padding="4px" marginLeft="10px" />
        <Flex direction="column" margin="5px">
          <Text fontSize="xl" margin="0">
            {item.users.name}
          </Text>
          <Text margin="0">{item.text}</Text>
        </Flex>
      </Flex>
    </Box>
  );
};
export default ChatItem;
```

## GraphQL Hooks and React

So far, we’ve shown how to use [`@apollo/react-hooks`](https://www.apollographql.com/docs/react/api/react-hooks/) with React. Now let’s walk through how to set up and use [`graphql-hooks`](https://github.com/nearform/graphql-hooks) with a React application.

```jsx
npm install graphql-hooks subscriptions-transport-ws
```

- [`graphql-hooks`](https://github.com/nearform/graphql-hooks) provides hooks for GraphQL operations, such as `useQuery`, `useMutation`, and `useSubscriptions`
- [`subscriptions-transport-ws`](https://github.com/apollographql/subscriptions-transport-ws) -provides `SubscriptionClient` for WebSocket to use in GraphQL subscriptions

`App.js`:

```jsx
import React from "react";
import customTheme from "./theme";
import { ThemeProvider } from "@chakra-ui/core";
import { GraphQLClient, ClientContext } from "graphql-hooks";
import { SubscriptionClient } from "subscriptions-transport-ws";
import Routes from "./routes";
import "./App.css";
const client = new GraphQLClient({
  url: "https://hasura-infiite-loader.herokuapp.com/v1alpha1/graphql",
  subscriptionClient: new SubscriptionClient(
    "ws://hasura-infiite-loader.herokuapp.com/v1alpha1/graphql"
  )
});
function App() {
  return (
    <ClientContext.Provider value={client}>
      <ThemeProvider theme={customTheme}>
        <div className="App">
          <Routes />
        </div>
      </ThemeProvider>
    </ClientContext.Provider>
  );
}
export default App;
```

We created a GraphQL client with HTTP and WebSocket links and used it with Context Provider.

Now that we’ve set up GraphQL Hooks, we can use it in our components. We’ll create the same components we created during the `@apollo/react-hooks` setup.

Spoiler alert: there is not much of a change in components.

![Chat App Components — GraphQL](https://i0.wp.com/blog.logrocket.com/wp-content/uploads/2020/03/chat-app-components-graphql.png?resize=330%2C390&ssl=1)

### Login component

This will be similar to the Apollo setup except for two things: we’re going to import `graphql-hooks`, and we don’t need `graphql-tags` to define the schema.

Otherwise, the steps are the same.

```jsx
import React, { useState, useEffect } from "react";
import { useForm } from "react-hook-form";
import {
  FormErrorMessage,
  FormLabel,
  FormControl,
  Input,
  Button,
  Box
} from "@chakra-ui/core";
import { useMutation } from "graphql-hooks";
const LOGIN_USER = `
  mutation InsertUsers($name: String!, $password: String!) {
    insert_users(objects: { name: $name, password: $password }) {
      returning {
        id
        name
      }
    }
  }
`;
const Login = ({ history }) => {
  const [state, setState] = useState({
    name: "",
    password: ""
  });
  const [insert_users, { data }] = useMutation(LOGIN_USER);
  useEffect(() => {
    const user = data && data.insert_users.returning[0];
    if (user) {
      localStorage.setItem("user", JSON.stringify(user));
      history.push("/chat");
    }
  }, [data]);
  const { handleSubmit, errors, register, formState } = useForm();
  function validateName(value) {
    let error;
    if (!value) {
      error = "Name is required";
    }
    return error || true;
  }
  function validatePassword(value) {
    let error;
    if (value.length <= 4) {
      error = "Password should be 6 digit long";
    }
    return error || true;
  }
  const onInputChange = e => {
    setState({ ...state, [e.target.name]: e.target.value });
  };
  const onSubmit = () => {
    insert_users({ variables: { name: state.name, password: state.password } });
    setState({ name: "", password: "" });
  };
  return (
    <Box w="50%" margin="auto">
      <form onSubmit={handleSubmit(onSubmit)}>
        <FormControl isInvalid={errors.name}>
          <FormLabel htmlFor="name">Name</FormLabel>
          <Input
            name="name"
            placeholder="name"
            onChange={onInputChange}
            ref={register({ validate: validateName })}
          />
          <FormErrorMessage>
            {errors.name && errors.name.message}
          </FormErrorMessage>
        </FormControl>
        <FormControl isInvalid={errors.password}>
          <FormLabel htmlFor="name">Password</FormLabel>
          <Input
            name="password"
            type="password"
            placeholder="password"
            onChange={onInputChange}
            ref={register({ validate: validatePassword })}
          />
          <FormErrorMessage>
            {errors.password && errors.password.message}
          </FormErrorMessage>
        </FormControl>
        <Button
          mt={4}
          variantColor="teal"
          isLoading={formState.isSubmitting}
          type="submit"
        >
          Submit
        </Button>
      </form>
    </Box>
  );
};
export default Login;
```

### Chat component

`Chat`/`index.js`

```jsx
import React, { useState, useEffect } from "react";
import { Box, Flex, Input } from "@chakra-ui/core";
import ChatItem from "../ChatItem";
import { useMutation, useSubscription } from "graphql-hooks";
const MESSAGES_SUBSCRIPTION = `
  subscription {
    messages {
      id
      text
      users {
        id
        name
      }
    }
  }
`;
const SUBMIT_MESSAGES = `
  mutation InsertMessages($text: String!, $userid: Int!) {
    insert_messages(objects: { text: $text, created_user: $userid }) {
      returning {
        text
        created_user
        users {
          name
          id
        }
        id
      }
    }
  }
`;
const Chat = () => {
  const [state, setState] = useState({
    text: "",
    data: []
  });
  const [errors, setErrors] = useState(null);
  const [insert_messages, { returnData }] = useMutation(SUBMIT_MESSAGES);
  //   const { loading, error, data: { messages } = [] } = useSubscription(
  //     MESSAGES_SUBSCRIPTION
  //   );
  useSubscription({ query: MESSAGES_SUBSCRIPTION }, ({ data, error }) => {
    if (errors && errors.length > 0) {
      setErrors(errors[0]);
      return;
    }
    setState({ ...state, data: data.messages });
  });
  const onInputChage = e => {
    setState({ ...state, [e.target.name]: e.target.value });
  };
  const onEnter = e => {
    if (e.key === "Enter") {
      let user = localStorage.getItem("user");
      user = JSON.parse(user);
      insert_messages({ variables: { text: state.text, userid: user.id } });
      setState({ ...state, text: "" });
    }
  };
  return (
    <Box h="100vh" w="40%" margin="auto">
      <Flex direction="column" h="100%">
        <Box bg="blue" h="90%" w="100%" border="solid 1px" overflowY="scroll">
          {state.data.map(message => {
            return <ChatItem item={message} />;
          })}
        </Box>
        <Box bg="green" h="10%" w="100%">
          <Input
            placeholder="Enter a message"
            name="text"
            value={state.text}
            onChange={onInputChage}
            onKeyDown={onEnter}
            size="md"
          />
        </Box>
      </Flex>
    </Box>
  );
};
export default Chat;
```

`ChatItem`/`index.js`

```jsx
import React from "react";
import { Box, Flex, Avatar, Heading, Text } from "@chakra-ui/core";
const ChatItem = ({ item }) => {
  return (
    <Box h="60px">
      <Flex direction="row" alignItems="center" height="100%">
        <Avatar
          size="sm"
          name={item.users.name}
          padding="4px"
          marginLeft="10px"
        />
        <Flex direction="column" margin="5px">
          <Text fontSize="xl" margin="0">
            {item.users.name}
          </Text>
          <Text margin="0">{item.text}</Text>
        </Flex>
      </Flex>
    </Box>
  );
};
export default ChatItem;
```

## Key takeaways

Let’s summarize the difference between `graphql-hooks` and `apollo-react-hooks` by analyzing some of the main concepts.

### GraphQL operations

As far as GraphQL operations such as query, mutation, and subscription, both libraries are similar. They both have the same set of hooks that can be used for GraphQL operations.

### Caching

Both Apollo hooks and GraphQL hooks have options for caching.

GraphQL Hooks include [`graphql-hooks-memcache`](https://github.com/nearform/graphql-hooks/tree/master/packages/graphql-hooks-memcache).

```jsx
import { GraphQLClient } from 'graphql-hooks'
import memCache from 'graphql-hooks-memcache'

const client = new GraphQLClient({
  url: '/graphql',
  cache: memCache()
})
```

Meanwhile, Apollo Hooks provides [`apollo-cache-inmemory`](https://www.apollographql.com/docs/react/caching/cache-configuration/).

```jsx
import { InMemoryCache } from 'apollo-cache-inmemory';
import { HttpLink } from 'apollo-link-http';
import { ApolloClient } from 'apollo-client';

const client = new ApolloClient({
  link: new HttpLink(),
  cache: new InMemoryCache()
});
```

Another advantage of [Apollo caching](https://www.apollographql.com/docs/react/caching/cache-configuration/#configuring-the-cache) is that there are additional options to configure the caching, such as getting the data ID from the object and cache redirect. Apollo also provides options for [cache interaction](https://www.apollographql.com/docs/react/caching/cache-interaction/).

## Middleware

Since Apollo Provides an [Apollo Link](https://blog.apollographql.com/apollo-link-the-modular-graphql-network-stack-3b6d5fcf9244), we can control the execution of the GraphQL operation by providing links. Common Apollo link functionalities include retries, live queries, alternative caching layers, and offline support.

### Server-side rendering

Both [GraphQL Hooks](https://github.com/nearform/graphql-hooks/tree/master/packages/graphql-hooks-ssr) and [Apollo](https://www.apollographql.com/docs/react/api/react-ssr/) provide packages for server-side rendering. In my experience, both work well.

## Conclusion

You should now have a basic understanding of the packages for implementing React Hooks for GraphQL. So which one is best for your GraphQL project? There’s no right or wrong answer — it all depends on your app’s unique needs and your personal preference. I tend to gravitate toward `graphql-hooks` because it is simple to use and easy to implement, but I’d encourage you to try both and see which you like best.

* * *
## 200's only ‎✅: Monitor failed and show GraphQL requests in production 

While GraphQL has some features for debugging requests and responses, making sure GraphQL reliably serves resources to your production app is where things get tougher. If you’re interested in ensuring network requests to the backend or third party services are successful, [try LogRocket.](https://www2.logrocket.com/signup-lr)

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/jd2amkhuiynfjf3i33qk.png)

[LogRocket](https://www2.logrocket.com/signup-lr) is like a DVR for web apps, recording literally everything that happens on your site. Instead of guessing why problems happen, you can aggregate and report on problematic GraphQL requests to quickly understand the root cause. In addition, you can track Apollo client state and inspect GraphQL queries' key-value pairs.

LogRocket instruments your app to record baseline performance timings such as page load time, time to first byte, slow network requests, and also logs Redux, NgRx, and Vuex actions/state. [Start monitoring for free.](https://www2.logrocket.com/signup-lr)
* * *

The post [Comparing hooks libraries for GraphQL](https://blog.logrocket.com/comparing-hooks-libraries-for-graphql/) appeared first on [LogRocket Blog](https://blog.logrocket.com).