Tutorials on Apollo

Learn about Apollo from fellow newline community members!

  • React
  • Angular
  • Vue
  • Svelte
  • NextJS
  • Redux
  • Apollo
  • Storybook
  • D3
  • Testing Library
  • JavaScript
  • TypeScript
  • Node.js
  • Deno
  • Rust
  • Python
  • GraphQL
  • React
  • Angular
  • Vue
  • Svelte
  • NextJS
  • Redux
  • Apollo
  • Storybook
  • D3
  • Testing Library
  • JavaScript
  • TypeScript
  • Node.js
  • Deno
  • Rust
  • Python
  • GraphQL

Should I Directly Access Data From the Apollo Client or From React Component State?

Consider the following code snippet of a React component, <App /> , that... You may have noticed that the data sent back by the mutation provides the user's information in a logIn field, and any data returned from a successful mutation automatically gets added to the local Apollo Client cache. Therefore, why do we have a user state variable when we could just access the user's information via the data field in the mutation result object? For example, like this: This can be considered an anti-pattern, but data can be either undefined or { logIn: { id: ..., token: ..., ... } } . Therefore, you would need to check if data is undefined or not directly in the body (and rendering section) of the <App /> component. Even after you determine that data is not undefined , you would still need to perform the same number of checks as before for the logIn property, etc. By using the setUser approach, you start with a baseline user object with its properties initialized to null , so you don't have to check if the user is undefined in the body (and rendering section) of the <App /> component (one less check). Additionally, with this approach, you only perform the checks for the data inside the onCompleted function. You could directly access the cache via the update function, which is called after the mutation completes and provides the cache as an argument, like so: However, the cache at this point doesn't actually have user data in the cache (to confirm this, print JSON.stringify(cache.data.data) in the update function). The user data is provided separately as the update function's second argument. You would need to manually modify the cache so that it has this user . Once the cached data is updated, the change gets broadcasted across the application and re-renders the components with active queries that correspond to the updated data. So you would need to put into each component that relies on user a call to useQuery that fetches the user . On initial page load, it's an extra, unnecessary network request since the LOG_IN already gets us the user data. But after the initial page load, if the user decides to log in or log out, then getting the user will be based on the update to the cache and having its updated user data be broadcasted to the useQuery s. In this case, it's more ideal to use setUser if it means one less network request on initial page load. As always, it's completely up to you how you want to manage state in your applications, but be sure to evaluate the trade-offs for each possible solution and pick the one that best suits your situation. Check out this Codesandbox example to see what I mean: https://codesandbox.io/embed/mutations-example-app-final-tjoje?fontsize=14&hidenavigation=1&theme=dark If you want to learn more advanced techniques with TypeScript, GraphQL and React, or learn how to build a production-ready Airbnb-like application from scratch, then check out our TinyHouse: A Fullstack React Masterclass with TypeScript and GraphQL :

Thumbnail Image of Tutorial Should I Directly Access Data From the Apollo Client or From React Component State?

Optimistic UIs with React, Apollo Client and TypeScript (Part II) - Optimistic Mutation Results

Disclaimer - Please read the first part of this blog post here before proceeding. It walks through the initial steps of building a messages client that fetches messages from a GraphQL API server. If you are already familiar with the basics of Apollo Client, and only want to know how to update a UI optimistically (for mutation results), then download the project from the part-1 branch of the GitHub repository here and follow the directions in the README.md file to set up the project. In the second part of this tutorial series, we will implement the remaining functionality of the messages client: By the end of this tutorial, you will have recreated the optimistic UI found in Messages : For a user to send a message, the message client must send a request to the GraphQL API server to perform an addMessage mutation. Using the text sent by the user, this mutation creates a new message and adds it to the list of messages managed by the server. The addMessage mutation, which is defined in the GraphQL schema below, expects values for the text and userId variables. The text variable holds the new message's text, and the userId variable holds the ID of the user who sent the message. Once it finishes executing the mutation's resolver, the server responds back with the sent message. Unlike Apollo Client's useQuery Hook, which tells a GraphQL API server to perform a query (fetch data), Apollo Client's useMutation Hook tells a GraphQL API server to perform a mutation (modify data). Like the useQuery Hook, the useMutation Hook accepts two arguments: And returns a tuple with a mutate function and a result object: In the above snippet, the mutate function is named addMessage . The mutate function lets you send mutation requests from anywhere within the component. The result object contains the same properties as the result object returned by the useQuery Hook, such as data , loading and error . For the <MessagesClient /> component, the application can ignore this result object from the tuple. Since the mutation should cause the UI to update optimistically, the application does not need to present a loading message to indicate a mutation request being sent and processed. Therefore, it does not need to know when the mutation is in-flight. As for the data returned as a result of a successful mutation and the errors that the mutation may produce, we will handle those later on in this tutorial. The <MessagesClient /> component calls the useMutation Hook and destructures out the mutate function (naming it addMessage ) from the returned tuple. The <MessagesClient /> component contains an input field for the current user to type and send messages. First, let's create a ref and attach it to the <input /> element. The ref gives you access to the text typed into the <input /> element. Then, let's attach an event handler (named handleOnSubmit ) to the input field's parent <form /> element's onSubmit attribute that executes the addMessage mutate function when the user sends a message (submits the form with a non-empty input field). The handler calls addMessage , passing in (as the argument) an options object with a variables option, which specifies the values of all the variables required by the mutation. The addMessage mutation requires two variables: Once you finish making these adjustments to the <MessagesClient /> component, run/reload the application. When you send a message, the UI does not update with the message you just sent despite the server successfully processing the mutation request and sending back a response with this message. Typing message into input field: Sending message (submitting the form): Checking the response from the server: To update the UI with this message, we must update the messages stored in the Apollo Client cache. By default, Apollo Client stores the results of GraphQL queries in this local, normalized cache and uses cache APIs, such as cache.writeQuery and cache.modify , to update cached state. Anytime a field within the cache gets modified, queries with this field automatically refresh, which causes the components using these queries to re-render. In this case, the query within the <MessagesClient /> component has a messages field. Once the query resolves and returns with data that has this field (set to a list of messages), like this: Apollo Client normalizes and stores the data in the cache as a flat lookup table by...           As a result, the root level of the cache serves as a flat lookup table. To see this in action, add the update caching option to the addMessages options argument, and set this option to a function with two parameters: Apollo Client executes the update function after the addMessage mutation completes. When you log cache , you will see that cache contains metadata and methods available to an instance of InMemoryCache , which was specified as the Apollo Client's cache. Upon further inspection, you will find the fields messages and users (from the query operations) under cache.data.data.ROOT_QUERY . Logging  cache : Inspecting ROOT_QUERY  in the cache: Notice how Apollo Client stores the query responses using a normalization approach. The cache only keeps one copy of each piece of data, adjacent to ROOT_QUERY . This reduces the amount of data redundancy in the cache. Instead of repeating the same user data across every message, each message in the cache references the user by a unique identifier. This lets the Apollo Client to easily locate the user's data in its cache's flat lookup table. When you log mutationResult , you will see the message you just sent. To render this message to the UI, we must add it to the list of messages already cached by the Apollo Client. Any changes made to the cached query results gets broadcasted across the application and re-renders the components with those active queries. Within the update function, check if the mutation has completed and returned the sent message, like so: Then, we will directly modify the value of the cache's messages field with the cache.modify method. This method takes a map of modifier functions based on the fields that should be changed. Each modifier function supplies its field's current cached value as a parameter, and the value returned by this function replaces the field's current value. In this case, the map will only contain a single modifier function for the messages field. Note : cache.modify overwrites fields' values. It does not merge incoming data with fields' values. If you log existingMessagesRefs , then you see that it points to the value of the messages field under ROOT_QUERY (a list of objects with references to the actual messages in the cache's flat lookup table). To add the message to the cache, the modifier function must... Note : The fragment option of the argument passed to the cache.writeFragment method determines the shape of the data to write to the cache. It should match the shape of the data specified by the query. Reload the application. When you send a message, the UI now updates with the message you just sent. However, this UI update happens after , not before , the server successfully processes the mutation request and sends back a response with this message. To better observe this, simulate slow network speeds in the developer console and send a message again. Let's make the UI feel more responsive by optimistically updating it when the user sends a message. Displaying the mutation result before the GraphQL API server sends back a response gives the illusion of a performant UI and keeps the user engaged in the UI without any delays. When the server eventually sends back a response, the result from the server replaces the optimistic result. If the server fails to persist the data, then Apollo Client rollbacks the optimistic UI updates. To optimistically update the UI to show the message immediately after the user sends a message, provide an optimisticResponse option to the addMessages options argument, and set this option to the message that should be added to the cache. The message must be shaped exactly like the message returned by the addMessage mutation, and it must also include id and __typename attributes so that the Apollo Client can generate the unique identifiers necessary for the cache to remain normalized. Any optimistic update for the addMessage mutation goes through an optimistic mutation lifecycle : Altogether... ( src/components/MessagesClient.tsx ) If you find yourself stuck at any point while working through this tutorial, then feel free to visit the part-2 branch of this GitHub repository here for the code. If you simulate offline behavior in the developer tools and try to send a message, then you will see that the UI optimistically updates with the message for a brief moment before removing it from the UI. In the Messages app, when a message fails to be delivered, the message remains in the UI, but a red exclamation point icon appears next to the message to give the user a chance to resend the message. Continue on to the final part of this tutorial here , to learn how to handle such situations in optimistic UIs.

Thumbnail Image of Tutorial Optimistic UIs with React, Apollo Client and TypeScript (Part II) - Optimistic Mutation Results

I got a job offer, thanks in a big part to your teaching. They sent a test as part of the interview process, and this was a huge help to implement my own Node server.

This has been a really good investment!

Advance your career with newline Pro.

Only $30 per month for unlimited access to over 60+ books, guides and courses!

Learn More

Building a GraphQL Application with Vue 3 and Apollo

RESTful APIs adhere to a reliable architectural standard for transferring data statelessly over the HTTP protocol. Every endpoint of an API semantically describes how a resource should be created ( POST ), read ( GET ), updated ( PUT / PATCH ), deleted ( DELETE ), etc. Large, data-driven applications consume data from multiple third-party/in-house sources, and each one exposes a unique set of endpoints to manage different resources. Adapting these applications to support a wide range of platforms and device sizes (commonly mobile, desktop and web) may present several problems: Using Facebook's GraphQL query language, the client specifies its exact data requirements to the server via a single endpoint. Establishing a schema (written with the syntax of the GraphQL Schema Definition Language) creates a contract between the client and server that defines what data can be read from and written to the data graph by the client. This data graph centralizes all of the APIs consumed by your application by mapping each field to a resolver that populates it with a value retrieved from an endpoint of one of these APIs, a database, etc. A client can fetch data from a GraphQL server via plain HTTP and then manually update the UI accordingly. However, GraphQL clients such as Apollo Client abstract away the low-level implementation details of these features underneath a declarative API. Built by the Apollo GraphQL team, Apollo Client is an open-source GraphQL client that provides a lot of out-of-the-box functionality for communicating with a GraphQL server: To integrate Apollo Client into an application using another JavaScript library/framework besides React, which Apollo Client already has built-in support for, there exists view integration libraries within the Apollo ecosystem that provide bindings for Vue , Svelte , Angular , Ember and Web Components . The Vue Apollo library integrates Apollo Client into a Vue application. Different versions of Vue Apollo are compatible with different versions of Vue: Although Vue Apollo v4 is still in active development (alpha phase), it offers support for Vue 3's Composition API , which collocates the methods corresponding to component options ( watch , computed , etc.) and lifecycle hook registrations ( onMounted , onUnmounted , etc.) within a single component option, setup . Using Vue Apollo v4 methods, such as useQuery and useMutation , the data requirements are also placed within the setup method. This approach makes it much easier to reason about a component's code compared to the Vue Apollo Options API approach, which places the data requirements within an apollo component option (independent of the other code placed within the remaining component options). Below, I'm going to show you: Using Vue 3's Composition API and the Vue Apollo (v4) library, we will be building the following GitHub search client: To start, download this project from GitHub: This repository is based on a custom Vue CLI project template that runs Vue 3 and includes support for TypeScript, ESLint and Prettier. If you want to learn how to manually set up the base structure of this project, then proceed to the next section (" Installation "). Otherwise, you may skip the " Installation " section, download the already prepared project structure and proceed directly to the " GitHub GraphQL API " section. To generate a new Vue CLI project, run the following command in the terminal: When prompted with "Please pick a preset," select the "Manually select features" option: This project will support TypeScript. Press "Space" to select "TypeScript." When prompted with "Choose a version of Vue.js that you want to start the project with," select the "3.x (Preview)" option: Vue components will not be written with the class syntax. The Class API was officially dropped . This project will use Babel alongside TypeScript. For linting and code formatting, select the "ESLint + Prettier" option: Anytime changes to a file are saved, run the linter. For this project, let's place the Babel, ESLint, etc. configurations within their own dedicated files to avoid increasing the size of package.json . These answers are only for this project. In the future, you may want to try out different sets of project configurations to determine what specific tools make you more productive. To integrate type definitions from the schema of GitHub's GraphQL API , install @octokit/graphql-schema : Several type definitions are assigned nullable types , which will cause ESLint to raise the following error within your IDE. Inside of the .eslintrc.js file, turn off the rule @typescript-eslint/no-non-null-assertion . ( .eslintrc.js ) In 2017, GitHub publicly released its GraphQL API . GitHub's GraphQL API exposes a public schema for interacting with GitHub itself, whether fetching commit data or starring a repository, all accessible from a single endpoint. To send requests to GitHub's GraphQL API, generate an access token. This access token must be set to each request's Authorization header. When setting permissions for the access token, enable repository privileges. Create a .env file at the root of the project directory. Copy the 40 character-long access token to your clipboard. Set the environment variable VUE_APP_GITHUB_ACCESS_TOKEN to this access token. ( .env ) Note : Environment variables prefixed with VUE_APP_ can be accessed via process.env within Vue applications. Without this prefix, environment variables are undefined . First, install graphql , @apollo/client and @vue/apollo-composable as dependencies: To rapidly style the UI interface, we will be using the Tailwind CSS framework. Install tailwindcss , postcss and autoprefixer as dependencies: Then, create a minimal Tailwind configuration file ( tailwind.config.js ) at the root of the project directory. Note : The -p flag creates a minimal PostCSS configuration file ( postcss.config.js ) at the root of the project directory, alongside the generated tailwind.config.js . Inside of tailwind.config.js , set the purge option to a list of filenames/globs for PurgeCSS to analyze and remove unused CSS. ( tailwind.config.js ) Inside of public/index.html , add these two CSS classes to the <body /> element: ( public/index.html ) When you run the application, you will encounter the following error: Although the latest version of the tailwindcss PostCSS plugin (v2) is compatible with latest version PostCSS (v8), other tools within the PostCSS ecosystem may not yet be compatible with this version of PostCSS. To resolve this error, uninstall tailwindcss , postcss and autoprefixer , and then reinstall these dependencies with the PostCSS (v7) compatibility build. Inside of main.ts (the entry point of the Vue 3 application), create an ApolloClient instance. Let's pass an object containing configuration options to the Apollo Client: For this application, we will define two links: To inject the Apollo Client into the application and allow child components to access the Apollo Client, call the provide method within the createApp 's setup method to "provide" this client to the application and its children components. Since this application only interacts with a single GraphQL API, set this client as the default client. Putting it altogether... ( main.ts ) Our application requires three child components: By default, the reactive searchOptions object, which represents the arguments passed to the GitHub GraphQL API's search query, is dynamically assigned to the prop search-options of the <RepositoryList /> component. Any changes to searchOptions , particularly to query , which corresponds to the value of the search bar's input, will cause the <RepositoryList /> component to retrieve a new list of repositories. The value of query is changed whenever the search event is emitted from the <SearchBar /> component, which occurs on changes to the value of its input. ( src/App.vue ) Typing a query emits a "search" event with the current query and triggers the search function in the <App /> component. This search function sets the value of the query field in the reactive searchOptions object. Debounce the handleInputChange event handler to avoid sending the search event on every single input change. ( src/components/SearchBar.vue ) When an event is fired, this debounce function starts a timer and waits for a specific time period to elapse before calling its corresponding event handler. If another event is fired during this time period, then the previous event is ignored. The timer resets and must wait for the specific time period (now reset) to elapse before calling the new event's corresponding event handler. This debounce function invokes the event handler on the trailing edge of the timeout. ( src/utils.ts ) Store the queries and mutations within a single file. This application requires only one query and two mutations: If you decide to add more queries/mutations that return a repository/repositories, and you request for the same repository fields for those queries/mutations, then use the repo fragment to keep your code DRY. ( src/graphql/documents.ts ) Inside of the <RepositoryList /> component, fetch a list of repositories based on the searchOptions passed from the <App /> parent component. To fetch this list of repositories, the component executes the composition function useQuery , which accepts a GraphQL document ( SEARCH_REPOS ) as the first argument and query arguments ( searchOptions ) as the second argument. This function is compatible with the setup function of Vue 3's Composition API. useQuery returns an object that contains several Ref values: Sometimes, a query may return multiple top-level objects. To pick a single object from the result object returned by useQuery , use the useResult composition function. Instead of referencing the repositories from the result object as result.search.edges in the component's template, it can just be referenced as repositories . Plus, the default value assigned to repositories is the second argument passed to useResult (in this case, an empty array). ( src/components/RepositoryList.vue ) Inside of the <Repository /> component, there is a button for starring/unstarring a repository, depending on whether or not you have starred the repository previously. If you have not yet starred the repository, then clicking the button will star the repository, and vice-versa. The event handler calls either the unstarRepo or starRepo functions to unstar or star a repository respectively. Each of these functions execute the composition function useMutation , which accepts a GraphQL document ( ADD_STAR or REMOVE_STAR ) as the first argument and options (an object containing mutation arguments via the variables property, etc.) as the second argument. Similar to useQuery , this function is compatible with the setup function of Vue 3's Composition API. When a repository is starred/unstarred, we must update the cache to reflect this mutation. To understand why this is important, let's walkthrough an example. Imagine you typed the query "facebook" into the search bar's input. This will fetch all repositories relevant to "facebook" from GitHub's GraphQL API. Suppose you have already starred the facebook/react repository, and you decide to unstar it. After you unstar it, you decide to type the query "google" into the search bar's input. This will fetch all repositories relevant to "google" from GitHub's GraphQL API. If you again type the query "facebook" into the search bar's input, then this will fetch all repositories relevant to "facebook" from the Apollo Client's cache . What was cached previously for this query was a list of repositories relevant to "facebook," including the facebook/react repository. However, this repository was cached when it was still starred. Therefore, we must modify this repository in the cache to reflect that it was recently unstarred. To update the cache, set the update property in the options object to a function that provides an instance of the cache and the data returned from a mutation. This function will call the overrideMutationStarCache , which will read the already cached data (via the cache 's readQuery method) and write the result of the mutation to the appropriate repository entity (via the cache 's writeQuery method). Don't forget to also increment/decrement the stargazers count! Putting it altogether... ( src/components/Repository.vue ) Run the application locally: Visit localhost:8080 in a browser to interact with the application. In this blog post, we only explored a very small subset of the GitHub GraphQL API. Try experimenting with other aspects of the public schema of the GitHub GraphQL API. For a more difficult challenge, try connecting an existing Vue 3 application to a custom GraphQL server. If you want to learn more about Vue 3, then check out Fullstack Vue :

Thumbnail Image of Tutorial Building a GraphQL Application with Vue 3 and Apollo

Getting Started with GraphQL in React using Apollo Client

Apollo is a great interface for fetching and managing data through GraphQL. When we’re building applications with GraphQL, it’s important to manage data effectively to have a smooth development experience. This is where Apollo steps in, and acts as an abstraction layer over GraphQL (which is just a query language) , and provides a robust platform for data fetching. The power of Apollo lies with how much we get out of the box (it’s a lot). We don’t need to do lengthy custom setups or configurations and can get started right away. Here, we’ll be discussing the benefits and usage of Apollo Client with ReactJS, but it’s important to note that most of the same features are also available in Angular and Vue. Before we dive deeper into Apollo, let’s briefly discuss GraphQL. GraphQL is a query language, built by developers at Facebook that emphasizes predictable results by building schemas for building queries. We use a tree structure to fetch data through a single central API endpoint. With traditional REST APIs, we are usually exposing multiple APIs for different purposes. For example, we might have an API to fetch books, and a different API to fetch authors. Similarly, we may have APIs to get a singular book or author. With GraphQL, we only hit a single endpoint, but we use fields to fetch only the data we need, such as only the name of the book, in a sea of different available parameters made available by the back-end. By making a single request, our application can be fast even on slow mobile networks. The type system of GraphQL keeps the API structure robust, and the dev tools help us see the schema definitions to easily debug our requests. Moreover, it solves the problem of over-fetching and under-fetching, as we’re able to get exactly the data we need in one hit. Its optimistic UI and caching make all interaction with the server super fast and snappy. On the server-side, we import the required libraries and create schemas for Queries and Mutations, respectively. This prevents us from spending time thinking of complex API flows. Queries are used to read data, whereas Mutations are used to create, update, or delete the data. Here is a very basic example from the GraphQL documentation: First, we build the schema where all our possible queries lie, Now, we can create a root resolver that hosts all our functions corresponding to the queries we have created: Finally, we can initialize our application with GraphQL. The algorithm itself is very simple, it resolves each field before diving inside and doing the same until all the fields are resolved. After that, the result is returned in the required format. To describe and initiate our queries on the front-end, we can use the graphql library to hook into our React components, this will give us our resultant data as props. More often, people choose to go with libraries such as Apollo and Relay. Here, we’ll be discussing how Apollo specifically provides us with a toolkit to make our lives easier when working with GraphQL. Firstly, we need to include the required functions from apollo-client, apollo-link-http and apollo-cache-inmemory. We can create a client instance through ApolloClient, where we’ll pass two things: Now, we can call our query function with the defined query. Here, we’re getting all books for authors that are aged less than or equal to 25. Note, we’re using the JavaScript template syntax to write our queries. If using the graphQL extension, it will also provide us with syntax highlighting. We can do much more with queries like this, for example, we may choose to hit a different resolver to get all the books of a specific author. As Apollo uses Context API under the hood, to enable it to access our components, we need to wrap our root element with ApolloProvider. Next, we need to define our query. It’s better to create a folder structure where all our queries and mutations are in specific folders so it’s easier to navigate during development. Here, we’ll create a userQueryBooksByAuthor.js file, where we’ll define and export our query. Now, we can import this in the file for our React component where we’ll be calling this query and use it with the hooks Apollo provides. useLazyQuery allows us to query programmatically on events. For example, we click a button to load the books, in that case, the click handler function will look something like this: And to call it: Here, we’re passing the authorName from our click function, but we could also have this come from anywhere, such as a state variable. If we wanted to run the query every time a component loads, we can call the useQuery hook instead, in this way: Now, all we need to do is conditionally render our data. We can simply do that in our return statement in this fashion: Mutating data with Apollo Hooks is just as easy. We can call the useMutation hook, pass in the required variables to update our data, and get our results back. First, we initialize our hook and create our useMutationUpdateAuthorName.js file in our mutations folder: And, Now, we can call it conditionally. Like before, we’ll call the mutation on a button click. And to call it: Typically, when we’re working with REST APIs, we need to have some sort of state management solution for our React apps. This is because we need to keep track of our data, loading states, and success/error responses. This can sometimes make our code harder to navigate. However, Apollo provides us with caching as well as variables that hold the loading and API call result states directly. This means we don’t need to create further state variables, as we can just fetch them out of the query or mutation that we run as seen in the previous example. Moreover, we don’t need to store the fetched data in state either. Since Apollo caches all the results, if we query for the same data again, it will avoid making unnecessary API calls and instead look into the memory first to find a cached version of the call. From experience, it's clear that GraphQL is being considered more day by day by developers against traditional REST servers. One common use-case I’ve encountered is fetching data from Content Management Systems, where a specific data model is defined. This makes it easy to think of our data in a tree structure and to fetch what we need based on conditions quickly and efficiently. There’s no doubt that it allows developers to think of a different approach when handling data management between clients and servers. And Apollo is right at the forefront, providing even more features and possibilities to make things convenient for developers.

Thumbnail Image of Tutorial Getting Started with GraphQL in React using Apollo Client

How to build React Native apps with GraphQL and Apollo

GraphQL is described as a query language for APIs. It is also considered as an alternative to REST and has been adapted more frequently in the last few years. Do you have a GraphQL endpoint already setup but you are looking forward to gaining some insight on how to gracefully consume this endpoint in a React Native app? Together, let us build a demo app that leverages an integration between Apollo Client, React Native and Expo . Apollo has an entire ecosystem based on to build GraphQL applications. It could be used to develop client-side and server-side apps separately. Apollo has more features and support than its open-source competitors in GraphQL for JavaScript world for now. The main objectives of this tutorial going to cover are: Before we get started, make sure you have installed the following on your local development machine. Do note that, to follow along with this tutorial, you need some basic knowledge of React Native and Expo SDK. You are also required to have Expo Client installed either on a simulator device or a real device. Throughout this tutorial, I am going to rely on and use the iOS simulator. The demo app we are constructing should work on Android devices as well. Create a new React Native/Expo app using the following command. Make sure to navigate to the directory once the project has generated. When generating an Expo app, you are prompted some questions by the cli interface as shown below. Make sure you choose expo-template-blank . The rest of the questions can have default answers as suggested. The next step is to install dependencies that we are going to use to build this app. You will learn about each individual dependency whenever necessary in the rest of the tutorial. Do note that, some of these dependencies are peer dependencies and you might not use them directly. Open a terminal window and install the following. After the dependencies have installed, open App.js file from the root of the project in your favorite code editor or IDE. Let us replace some of the default contents with some meaningful UI components such as custom header. To make sure everything works, open the terminal window. Execute the command expo start that triggers the Expo client app to run. Press i if you are using an iOS simulator or a if you are using an android emulator. When the App component renders for the first time, you are going to get the following output: With the base app running, you are ready to build further. Let us explore a way to configure the Apollo client in our app in this section. Create a new file called Client.js inside a directory src/graphql . The configuration part is going to fit inside this file. Import the following statements to begin the configuration process. Three different packages are being imported in the above code snippet. The apollo-client and apollo-cache-inmemory are used to integrate GraphQL client in a React or React Native app. Another package required to make it work is called apollo-link . But in our app, we are going to use a variant called apollo-link-rest . Why the variant? The reason being is that this package allows the app to use third-party APIs that do not have a GraphQL endpoint. That means, they tend to have a REST endpoint. One real-time API is NewsAPI . This package is going to help us transmit the query to the REST endpoint in a GraphQL query. In the Client.js file, start by adding a link from the constructor RestLink and pass the API key as field inside headers object. This object represents the value to be sent as headers on a request. Lastly, add the below configuration with the default cache and RestLink to complete the configuration of Apollo Client. Create a new file called Queries.js inside src/graphql directory. This file is going to contain the structure of the GraphQL query which is eventually going to fetch the result from the API. Start by importing gql from graphql-tag . Export a new query called Headlines as shown in the snippet below. This query is going to fetch top articles with fields such as title, the published location, the URL of the article and so on. Using the @rest directive, Apollo client knows how to parse the query. To use the previously created query, import it as well as the configured Apollo client inside the App.js file. Using the query Headlines the result should be fetched from the API whenever the component mounts as well as on the initial render of the app. This can be done by using the React Hook useEffect . Create a handler method requestHeadlines to invoke the query using Apollo Client. Invoking the query is simply done adding a promise. I am going to console.log the result from the query for now. With the Expo client, there is an option to Debug JS remotely. It opens the console tab in browser’s developer tools and lets you see results of log statements (just like in web development). Here is the result of the above query. When invoked, it fetches 20 headline objects in an array with all requested fields. In the last image, in the response, you will find a field called loading that indicates are the results being fetched or the response is complete. Using this can be helpful when adding an activity indicator to display the same message to the end-user in a real mobile app. Start, by importing the ActivityIndicator component from react-native. Also, to set a state for the loading indicator, import the hook useState . Inside the App component define the state for loading . Modify the return statement by adding an if-else statement based on the boolean value of the loading . After this step, you are going to get the following output: To make it stop and behave in the way the app requires, update the state of loading when the promise resolves inside the query handler method requestHeadlines . Refresh the Expo client and you will notice that after a few seconds, when the data is fetched, the loading indicator disappears and the screen UI is displayed as before. You are all set to display individual article component that is being fetched from the API endpoint. Add another state variable called articles . To render a list of data, let’s use the FlatList component from react-native. Update the articles state with the array from the response when the promise gets resolved inside the handler method requestHeadlines . The FlatList component requires three attributes to render a list of data items. Inside the src/components directory create a new file called Article.js . This component is going to display the title and source of each headline. The Article component is going to be a presentation component that receives everything from the App component as props. Add the following to the file. Import the Article component in App.js file for it to work. Go to the simulator or the device that is running the Expo client and you are going to see several headlines being fetched. That's it! Congratulations to you for sticking around till the end. I hope this post serves as the basis of your adventure in building React Native apps with GraphQL and Apollo.

Thumbnail Image of Tutorial How to build React Native apps with GraphQL and Apollo