How to use REST API with Apollo Client and GraphQL on a React/Next.js app

Avi Takiyar
JavaScript in Plain English
4 min readMar 20, 2021

--

Photo by designveloper.com

Apollo Client is a state management library like Redux which allows you to write GraphQL queries on the client-side. If you are building an application with a GraphQL server, Apollo Client is one of the most suitable state management libraries as it has an amazing caching mechanism.

In this tutorial, I will fetch data from the OMDb Rest API to fetch movies by implementing it with Apollo Client to demonstrate how Rest APIs can be used in parallel with GraphQL.

Getting Started

Create a Next.js app

npx create-next-app <YOUR-APP-NAME>

In the case of React, use create-react-app.

Install Apollo Client and any peerDependencies

npm i @apollo/client apollo-link-rest graphql qs graphql-anywhere

Creating an HTTP Link

This is your already existing GraphQL Endpoint.

import { HTTPLink } from "apollo-link";

const httpLink = new HttpLink({
uri: 'https://server.myapp.com/graphql',
// other link options...
});

Creating a Rest Link

In our case, it’s an OMDB API to fetch movies.

import { RestLink } from ‘apollo-link-rest’;const restLink = new RestLink({
uri: “https://www.omdbapi.com/",
// other link options...
});

Setting up our Apollo Client

Now that we have configured our Rest and HTTP links, we can set them up in the Apollo Client.

import { ApolloClient, InMemoryCache, ApolloLink } from ‘@apollo/client’;const client = new ApolloClient({  link: ApolloLink.split(operation =>    operation.getContext().clientName === "rest",

// The string "rest" and "clientName" can be anything you want
restLink, // Apollo will send to this if clientName is "rest"

httpLink // Otherwise will send to this
),
cache: new InMemoryCache() // other options...
});

Writing our GraphQL Queries

Note that there are two OMDb endpoints. First for fetching data for a single movie and second for fetching a list of movies.

  1. https://www.omdbapi.com/?i=tt0371746&apikey=
  2. http://www.omdbapi.com/?s=iron&apikey=

Note: You can generate your API key from https://www.omdbapi.com/apikey.aspx

We must know that Apollo Client normalizes cache data based upon the typenames Therefore we must perform typename patching.

We can perform typename patching directly while writing our gql queries. But for the fields that contain sub-fields, it is advisable to add typename directly in the Apollo Client which I will illustrate in a while.

Fetch a single movie result by its movie ID

import { gql } from '@apollo/client';
export const getMovieQuery = gql` query($imdbID: String!) { movie(imdbID: $imdbID) @rest(type: "Movie", path: "?i={args.imdbID}&apikey=<YOUR_API>") { Error imdbID imdbRating Title Year Runtime Genre Director Country Plot Poster } }`;

Here, Movie is assigned as the typename. imdbID is used as a variable argument so that its value can be passed through the useQuery hook.

Fetch movie results by search parameters and page number

import { gql } from '@apollo/client';
export const getMoviesQuery = gql` query($search: String!, $page: Int!) { movies(search: $search, page: $page) @rest(type: "Movies", path: "?s={args.search}&apikey=<YOUR_API>&page={args.page}") { Error totalResults Search { Title Year imdbID Poster } } }`;

Here, Movies is assigned as the typename. search and page are used as a variable argument so that their values can be passed through the useQuery hook.

Note that the Search field contains sub-fields, therefore we must attach a typename to this field as well. We can directly attach a typename to the Search field in the query itself using @type(name: "Movie") directive, but it is advisable to modify the Rest Link instead.

Modifying our Rest Link

// ... same as previousconst restLink = new RestLink({  uri: "https://www.omdbapi.com/",  // Extra code to be added:  typePatcher: {    Movies: data => {      if (data.Search != null) {        data.Search = 
data.Search.map(search => ({
__typename: "Movie", ...search
}));
}
return data;
}
}
});

Note: Movies is the typename of the data fetched by our query. Therefore keep in mind that this name should be identical to the one used in the gql

Fetching data in our UI using useQuery hook

import { useQuery } from ‘@apollo/client’;// ...React/NextJS functionconst {loading, error, data} = useQuery(getMoviesQuery, {  variables: { search, page: 1 },
context: { clientName: 'rest' }
});if(loading) return 'Loading...';if(error) return 'No results found';console.log(data.movies);

Similarly,

import { useQuery } from ‘@apollo/client’;// ...React/NextJS functionconst {loading, error, data} = useQuery(getMovieQuery, {  variables: { imdbID: id },
context: { clientName: 'rest' }
});if(loading) return 'Loading...';if(error) return 'No results found';console.log(data.movie);

Note that we can use our GraphQL endpoints just like the way we do normally, that is without any context object.

That’s it. We are all done!

Conclusion

We know that GraphQL provides an amazing approach to our client-server applications but this does not mean that it prevents us from using the already existing REST APIs. REST and GraphQL shall always exist parallelly.

References

More content at plainenglish.io

--

--

I am MERN stack developer and a GraphQL enthusiast. Feel free to connect with me for building any project.