In this article, we will explore how to use the GraphQL query language with Apollo Client to efficiently and seamlessly fetch data from a server. By the end of your reading, you will learn how to use and install GraphQL and Apollo client, and two different approaches for how to perform query
and mutation
operations within react-apollo
.
GraphQL is a query language that uses a defined system to describe how a user should ask for data from an API. GraphQL requires that a user specify the exact data that needs to be transferred — most often from the server — which will then be loaded to the client side.
Before we learn about how specific query operations can be performed with Apollo, we will review some of the basic actions and operations that can be performed within the GraphQL query library.
A GraphQL query operation is concerned with basic data fetching from the server side.
{ query getItems { Items { id chair stool } } }
The above is a GraphQL query with name getItems
, that fetches id
, chair
, and stool
.
Adding the mutation
keyword performs basic CRUD (create, read, update and delete) operations in a GraphQL application.
{ mutation addUser(name: String!, email: String!){ addUser(name: $name, email: $email){ id name email created_at } } }
The above addUser
mutation returns a user’s name
, id
, email
, and create_at
fields when the user’s name and email is specified.
This is an event-based action that involves data transfer from the server to the client side when a particular event is executed. To create a subscription in GraphQL, we need to add the subscription type to our schema:
const typeDefs = gql` type Subscription { bookAdded: Book }`
The next step is to create a resolver
. Pubsub
is notified of an event in this case from within a mutation.
const BOOK_ADDED = 'BOOK_ADDED'; const resolvers = { Subscription: { bookAdded: { subscribe: () => pubsub.asyncIterator([BOOK_ADDED]), }, }, Mutation: { addBook(root, args, context) { pubsub.publish(BOOK_ADDED, { bookAdded: args }); return postController.addBook(args); }, }, };
The subscription is triggered by a publish
call inside the mutation.
Apollo serves as a state management library for local and remote data storage in a GraphQL application. Some of the basic operations that you can perform with the help of Apollo include: fetching, local state storage, and caching. The Apollo client also has a built-in integration with React that makes development much easier.
Some basic features of Apollo client include:
Apollo client allows a user to specify the exact data needed from an application programming interface. React uses a useQuery
Hook that enables us perform data retrieving and data fetching operations in a GraphQL application. An example from the official documentation can be found below:
function Feed() { const { loading, error, data } = useQuery(GET_DOGS); if (error) return <Error />; if (loading || !data) return <Fetching />; return <DogList dogs={data.dogs} />; }
With the help of the useQuery
Hook, we are able to fetch data from the GraphQL server that will lead to a UI update to reflect any changes.
Aside from the main fetching operations that can be performed with GraphQL, intelligent data caching operations can also be performed with with little to no configuration.
Below is an Apollo client configuration for data caching:
import { ApolloClient, InMemoryCache } from '@apollo/client'; const client = new ApolloClient({ cache: new InMemoryCache() });
Other benefits that come with Apollo client include:
If you have not set up your React application, start by running the following:
npx create-react-app
To make use of GraphQL and Apollo in your React application, you will need to install the following dependencies:
npm install apollo-boost graphql react-apollo
Your React application with GraphQL is now set up and ready for use!
To create a connection, first create an index.js
file and add the following snippet:
import ApolloClient from "apollo-boost";
import { ApolloProvider } from 'react-apollo';
const client = new ApolloClient({
uri: //graghql server url should be here
});
Next, wrap your app component with the ApolloProvider, passing the client as props:
ReactDOM.render(
<ApolloProvider client={client}>
<App />
</ApolloProvider>,
document.getElementById("root")
);
At the beginning, we talked about basic operations that you can perform with GraphQL including query
and mutation
. Now let’s, look at how to perform some of these operations with Apollo using the useQuery
Hook approach and the render props approach.
GraphQL queries involve reading and fetching of data. We can take two approaches in performing this operation with React Apollo: the useQuery
Hook approach and the render props approach.
useQuery
Hook approachFirst, let’s create a GraphQL query and name it getItems
as shown below:
import React from "react"; import { useQuery } from "react-apollo"; import { gql } from "apollo-boost"; const GET_ITEMS = gql` query GetItems { items { id oneitem } } `;
Next, create a functional component and pass the GraphQL query to the useQuery
Hook as follows:
function DisplayItems() { const { loading, error, data } = useQuery(GET_ITEMS); if (loading) return 'Loading...'; if (error) return `Error! ${error.message}`; return ( <select name="items"> {data.items.map(item => ( <option key={item.id} value={item.oneitem}> {item.oneitem} </option> ))} </select> ); }
The application will update when the new data is fetched or when an error occurs to reflect the new changes.
For the render props approach, the first step remains the same except for an additional importation of query from react-apollo
that we previously installed:
import React from "react"; import { Query } from "react-apollo"; import { gql } from "apollo-boost"; const GET_ITEMS = gql` query GetItems { items { id oneitem } } `;
Next, we will make use of query
by passing the created GraphQL query to it and using it as follows:
function DisplayItems() { if (loading) return 'Loading...'; if (error) return `Error! ${error.message}`; return ( <Query query={GET_ITEMS}> <select name="items"> {data.items.map(item => ( <option key={item.id} value={item.oneitem}> {item.oneitem} </option> ))} </select> </Query> ); }
Just like in the hooks approach, the application will either update to reflect the new data or return an error.
Mutation involves performing creating, updating, and deleting operations. As is the case with queries, we can make use of the hooks approach and render props approach when dealing with mutation.
First let’s import the dependencies including useMutation
imported from react-apollo
.
import React, { useState } from 'react'; import { useMutation } from 'react-apollo'; import { gql } from 'apollo-boost'; const ADD_TODO = gql` mutation AddTodo($type: String!) { addTodo(type: $type) { id type } } `;
Next is to create a functional component named AddToDo
and pass our ADD_TODO
mutation to the useMutation
Hook:
function AddTodo() { let input; const [addTodo, { data }] = useMutation(ADD_TODO); return ( <div> <form onSubmit={e => { e.preventDefault(); addTodo({ variables: { type: input.value } }); input.value = ''; }} > <input ref={node => { input = node; }} /> <button type="submit">Add Todo</button> </form> </div> ); }
Similar to the hooks approach, we need to import the necessary dependencies with a new mutation
importation from react-apollo
:
import React, { useState } from 'react'; import { useMutation } from 'react-apollo'; import { gql } from 'apollo-boost'; const ADD_TODO = gql` mutation AddTodo($type: String!) { addTodo(type: $type) { id type } } `;
To complete, pass the created mutation as follows:
function AddTodo() { let input; return ( <Mutation mutation={ADD_TODO}> <div> <form onSubmit={e => { e.preventDefault(); addTodo({ variables: { type: input.value } }); input.value = ''; }} > <input ref={node => { input = node; }} /> <button type="submit">Add Todo</button> </form> </div> </Mutation> ); }
GraphQL is a great choice when dealing with data fetching as it solves the over-fetching and under-fetching problems that come with RESTful APIs. Apollo Client makes GraphQL connection to a server easy, seamless, and efficient.
Install LogRocket via npm or script tag. LogRocket.init()
must be called client-side, not
server-side
$ npm i --save logrocket // Code: import LogRocket from 'logrocket'; LogRocket.init('app/id');
// Add to your HTML: <script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script> <script>window.LogRocket && window.LogRocket.init('app/id');</script>
Would you be interested in joining LogRocket's developer community?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowSOLID principles help us keep code flexible. In this article, we’ll examine all of those principles and their implementation using JavaScript.
JavaScript’s Date API has many limitations. Explore alternative libraries like Moment.js, date-fns, and the new Temporal API.
Explore use cases for using npm vs. npx such as long-term dependency management or temporary tasks and running packages on the fly.
Validating and auditing AI-generated code reduces code errors and ensures that code is compliant.
One Reply to "Data retrieval in GraphQL with react-apollo"
useQuery is not present in react-apollo