How to Call GraphQL Query, Mutation and Subscribe from React Native

Call GraphQL APIs from React Native

Here is an example to show how to call GraphQL Query, Mutation and Subscribe from React Native App. GraphQL is becoming the new way to use APIs in modern web and mobile apps. GraphQL is an alternative to REST that has been steadily gaining popularity since its release. Whereas with REST a developer would usually collate data from a series of endpoint requests, GraphQL allows the developer to send a single query to the server that describes the exact data requirement. For more information about GraphQL you can visit Official GraphQL website.

In this example we are not going to talk about GraphQL in deep as it is a huge topic in itself, we will see how to call GraphQL APIs by creating your React Native App as an Apollo Client.

Apollo Server and Apollo Client

Apollo Server is an open-source GraphQL server that’s compatible with any GraphQL client, including Apollo Client. It’s the best way to build a production-ready, self-documenting GraphQL API that can use data from any source.

Apollo Client helps you structure code in an economical, predictable, and declarative way. The core @apollo/client library provides built-in integration with React, and the larger Apollo community maintains integrations for other popular view layers.

Call GraphQL Query, Mutation and Subscription

Before moving further lets understand what is GraphQL Query, Mutation and Subscription?

Query is used to fetch/get records. It is simply like any GET request which can take some query params to filter the records.

Mutation is used to create/update records. We can imagine it as POST / PUT / PATCH / DELETE request.

Subscriptions maintain an active connection to your GraphQL server (most commonly via WebSocket). This enables your server to push updates to the subscription’s result over time. Subscriptions are useful for notifying your client in real time about changes to back-end data, such as the creation of a new object or updates to an important field.

Example Description

In this example, we will have 3 buttons to call

  1. Simple Query without payload
  2. Dynamic Query with payload by passing payload as variable
  3. Mutation by passing payload as variable

We will also Subscribe to GraphQL Subscription for creation of record, which means whenever a record got created GraphQL will publish a message for all the subscribers which we receiver in real time.

I hope after going through this example you will have a proper understanding of how to call GraphQL query and mutation and subscribe GraphQL subscription from React Native App. If you want to add some points then feel free to share them with us in comment below.

Let’s start with the example.

GraphQL Server Setup

For this example you will need GraphQL server to call query and mutation, if you have your own GraphQL server then you can ignore this section else can follow below steps to setup dummy GraphQL server.
1. Clone Repo

git clone https://github.com/SnehalAgrawal/about-react-dummy-graphql-apis.git

2. Jump into the directory

cd about-react-dummy-graphql-apis

3. Install node_module

npm install

4. Run GraphQL Server

npm start

This will start your GraphQL server for you

ReactNativeCallGraphQLQueryMutationServer

Once you start your GraphQL server you can move to next step to create React Native App which will subscribe and call Query and Mutation from this GraphQL server.

To Make a React Native App

Getting started with React Native will help you to know more about the way you can make a React Native project. We are going to use react native command line interface to make our React Native App.

If you have previously installed a global react-native-cli package, please remove it as it may cause unexpected issues:

npm uninstall -g react-native-cli @react-native-community/cli

Run the following commands to create a new React Native project

npx react-native init ProjectName

If you want to start a new project with a specific React Native version, you can use the --version argument:

npx react-native init ProjectName --version X.XX.X

Note If the above command is failing, you may have old version of react-native or react-native-cli installed globally on your pc. Try uninstalling the cli and run the cli using npx.

This will make a project structure with an index file named App.js in your project directory.

Installation of Dependencies

To install any dependency open the terminal and jump into the project using

cd ProjectName

As mentioned above to call GraphQL query and mutation from React Native App we will use Apollo Client library. To use it install @apollo/client and graphql

@apollo/client: This single package contains virtually everything you need to set up Apollo Client. It includes the in-memory cache, local state management, error handling, and a React-based view layer.
graphql: This package provides logic for parsing GraphQL queries.

npm install @apollo/client graphql --save

Because subscriptions maintain a persistent connection, they can’t use the default HTTP transport that Apollo Client uses for queries and mutations. Instead, Apollo Client subscriptions most commonly communicate over WebSocket, via the community-maintained subscriptions-transport-ws library. So install that also

npm install subscriptions-transport-ws --save

This command will copy all the dependencies into your node_module directory. –save is optional, it is just to update the dependency in your package.json file.

Code To Call GraphQL Query and Mutation

Open App.js in any code editor and replace the following code to call GraphQL Query, Mutation and to subscribe GraphQL subscription. Please check for the GraphQL URL if you are using your own GraphQL server.

App.js

// How to Call GraphQL Query and Mutation from React Native
// https://aboutreact.com/react-native-call-graphql-query-mutation-subscribe/

// import React in our code
import React, {useEffect, useState} from 'react';

// import all the components we are going to use
import {
  SafeAreaView,
  StyleSheet,
  View,
  Text,
  TouchableOpacity,
} from 'react-native';

import {
  ApolloClient,
  InMemoryCache,
  ApolloProvider
} from '@apollo/client';
import {gql} from '@apollo/client';
import {WebSocketLink} from '@apollo/client/link/ws';

const App = () => {
  const [user, setUser] = useState({});

  // Connection for the subscription
  const wsLink = new WebSocketLink({
    uri: `ws://localhost:4000/graphql`,
    options: {
      reconnect: true,
    },
  });

  // Initialize Apollo Client
  const client = new ApolloClient({
    uri: 'http://localhost:4000/graphql',
    headers: {
      // Header(if any)
      authorization: 'a1b2c3d4-a1b2-a1b2c3d4e5f6',
    },
    cache: new InMemoryCache(),
    // link WebSocketLink subscription
    link: wsLink,
  });

  useEffect(() => {
    // Creating Suscription Observer
    let observer = client.subscribe({
      query: gql`
        subscription userAdded {
          userAdded {
            name
            age
            email
            address
            password
          }
        }
      `,
    });

    // Observer callback
    let subscriptionObj = observer.subscribe((result) => {
      console.log('Subscription data => ', result.data.userAdded);
      setUser(result.data.userAdded);
    });

    return () => {
      // Unsubscribe subscription
      console.log('Unsubscribed');
      subscriptionObj.unsubscribe();
    };
  }, []);

  const simpleQuery = async () => {
    // Calling Simple Graph Query
    const {data, error} = await client.query({
      query: gql`
        query users {
          users {
            name
            age
            email
            address
            password
          }
        }
      `,
    });
    // In case Error in Response
    if (error) {
      alert(`error + ${JSON.stringify(error)}`);
      console.log('error', JSON.stringify(error));
      return;
    }
    alert(`Got Record of ${data.users.length} Users`);
    console.log('data', JSON.stringify(data));
  };

  const dynamicQuery = async () => {
    // Calling Graph Query with variables
    const {data, error} = await client.query({
      query: gql`
        query user($email: String!) {
          user(email: $email) {
            name
            age
            email
            address
            password
          }
        }
      `,
      variables: {
        email: 'netus.et.malesuada@ornarelectusjusto.co.uk'
      },
    });
    // In case Error in Response
    if (error) {
      console.log('error', JSON.stringify(error));
      alert(`error + ${JSON.stringify(error)}`);
      return;
    }
    console.log('data', JSON.stringify(data.user));
    alert(`Response: ${JSON.stringify(data.user)}`);
  };

  const simpleMutation = async () => {
    // Calling Graph Mutation with variables
    const {data, error} = await client.mutate({
      mutation: gql`
        mutation createUser(
          $name: String!
          $email: String!
          $age: Int!
          $address: String!
          $password: String!
        ) {
          createUser(
            name: $name
            email: $email
            age: $age
            address: $address
            password: $password
          )
        }
      `,
      variables: {
        name: `New User ${Math.random()}`,
        //'newuser@gmail.com',
        email: `newuser${Math.random()}@gmail.com`,
        age: 30,
        address: 'Demo Address',
        password: '12345',
      },
    });
    // In case Error in Response
    if (error) {
      alert(`error => ${JSON.stringify(error)}`);
      console.log('error', JSON.stringify(error));
      return;
    }
    alert(`Response: ${JSON.stringify(data.createUser)}`);
    console.log('data', JSON.stringify(data.createUser));
  };

  return (
    <ApolloProvider client={client}>
      <SafeAreaView style={styles.container}>
        <View style={styles.container}>
          <Text style={styles.titleText}>
            How to Call GraphQL Query and Mutation from React Native
          </Text>
          <View style={styles.innerContainer}>
            <Text style={styles.textStyle}>
              Run Simple Query (Get All User)
            </Text>
            <TouchableOpacity
              activeOpacity={0.7}
              style={styles.buttonStyle}
              onPress={simpleQuery}>
              <Text style={styles.buttonTextStyle}>Get Data</Text>
            </TouchableOpacity>
          </View>
          <View style={styles.innerContainer}>
            <Text style={styles.textStyle}>
              Run Dynamic Query by passing payload as variable {'\n'}
              (Get Single User by Email)
            </Text>
            <TouchableOpacity
              activeOpacity={0.7}
              style={styles.buttonStyle}
              onPress={dynamicQuery}>
              <Text style={styles.buttonTextStyle}>Get Data</Text>
            </TouchableOpacity>
          </View>
          <View style={styles.innerContainer}>
            <Text style={styles.textStyle}>
              Run Mutation by passing payload as variable {'\n'}
              (Create User)
            </Text>
            <TouchableOpacity
              activeOpacity={0.7}
              style={styles.buttonStyle}
              onPress={simpleMutation}>
              <Text style={styles.buttonTextStyle}>Add User</Text>
            </TouchableOpacity>
          </View>
          <View style={styles.innerContainer}>
            <Text style={styles.textStyle}>
              Subscription Data {'\n'}
              (Subscribed for Successfull user Creation)
            </Text>
            <Text style={{textAlign: 'center'}}>
              Last Added User: {JSON.stringify(user)}
            </Text>
          </View>
        </View>
        <Text
          style={{
            fontSize: 16,
            textAlign: 'center',
            color: 'grey',
          }}>
          www.aboutreact.com
        </Text>
      </SafeAreaView>
    </ApolloProvider>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: 'white',
    padding: 10,
    textAlign: 'center',
  },
  innerContainer: {
    marginTop: 16,
    backgroundColor: '#f5f5f5',
    padding: 16,
    marginBottom: 10,
  },
  titleText: {
    fontSize: 22,
    textAlign: 'center',
    fontWeight: 'bold',
  },
  textStyle: {
    fontSize: 16,
    textAlign: 'center',
    marginBottom: 10,
  },
  buttonStyle: {
    justifyContent: 'center',
    padding: 10,
    backgroundColor: '#8ad24e',
  },
  buttonTextStyle: {
    color: '#fff',
    textAlign: 'center',
  },
});

export default App;

To Run the React Native App

Open the terminal again and jump into your project using.

cd ProjectName

1. Start Metro Bundler

First, you will need to start Metro, the JavaScript bundler that ships with React Native. To start Metro bundler run following command:

npx react-native start

Once you start Metro Bundler it will run forever on your terminal until you close it. Let Metro Bundler run in its own terminal. Open a new terminal and run the application.

2. Start React Native Application

To run the project on an Android Virtual Device or on real debugging device:

npx react-native run-android

or on the iOS Simulator by running (macOS only)

npx react-native run-ios

Output Screenshots

ReactNativeCallGraphQLQueryMutation1   ReactNativeCallGraphQLQueryMutation2   ReactNativeCallGraphQLQueryMutation3   ReactNativeCallGraphQLQueryMutation4   ReactNativeCallGraphQLQueryMutation5

This is how you can call GraphQL query and mutation from React Native. If you have any doubts or you want to share something about the topic you can comment below or contact us here. There will be more posts coming soon. Stay tuned!

Hope you liked it. 🙂

1 thought on “How to Call GraphQL Query, Mutation and Subscribe from React Native”

  1. App.js (0:1)
    Unable to resolve module ‘module://graphql/language/printer.js’
    (Device)
    App.js (74:6)
    React Hook useEffect has a missing dependency: ‘client’. Either include it or remove the dependency array. (react-hooks/exhaustive-deps)

    Reply

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.