Integrating with React Native
You can use Apollo Client with React Native exactly as you do with React.js. Install it with npm
like so:
1npm install @apollo/client graphql
Then wrap your application in the ApolloProvider
component, like so:
1import React from 'react';
2import { AppRegistry } from 'react-native';
3import { ApolloClient, InMemoryCache, ApolloProvider } from '@apollo/client';
4
5// Initialize Apollo Client
6const client = new ApolloClient({
7 uri: 'http://localhost:4000/graphql',
8 cache: new InMemoryCache()
9});
10
11const App = () => (
12 <ApolloProvider client={client}>
13 <MyRootComponent />
14 </ApolloProvider>
15);
16
17AppRegistry.registerComponent('MyApplication', () => App);
For more information on setting up Apollo Client, see Getting started.
Example application
This sample application maintained by The GraphQL Guide uses Apollo Client with React Native.
Apollo Client Devtools
1. Using React Native Debugger
The React Native Debugger supports the Apollo Client Devtools:
Install React Native Debugger and open it.
Enable "Debug JS Remotely" in your app.
If you don't see the Developer Tools panel or the Apollo tab is missing from it, toggle the Developer Tools by right-clicking anywhere and selecting Toggle Developer Tools.
2. Using Flipper
A community plugin called React Native Apollo devtools is available for Flipper, which supports viewing cache data.
Install Flipper and open it.
Go to add plugin and search for
react-native-apollo-devtools
and install itAdd
react-native-flipper
andreact-native-apollo-devtools-client
as dev dependecy to react native app.Initialize the plugin with flipper on client side
TypeScript1 import { apolloDevToolsInit } from 'react-native-apollo-devtools-client'; 2 3 const client = new ApolloClient({ 4 // ... 5 }); 6 7 if (__DEV__) { 8 apolloDevToolsInit(client); 9 }
Consuming multipart HTTP via text streaming
By default, React Native ships with a fetch
implementation built on top of XHR that does not support text streaming.
For this reason, if you are using either @defer
or subscriptions over multipart HTTP—features that use text streaming to read multipart HTTP responses—there are additional steps you'll need to take to polyfill this functionality.
Install
react-native-fetch-api
andreact-native-polyfill-globals
and save them both as dependencies.In your application's entrypoint (i.e.
index.js
,App.js
or similar), import the following three polyfills and call each of thepolyfill*
functions before any application code:
1import { polyfill as polyfillEncoding } from "react-native-polyfill-globals/src/encoding";
2import { polyfill as polyfillReadableStream } from "react-native-polyfill-globals/src/readable-stream";
3import { polyfill as polyfillFetch } from "react-native-polyfill-globals/src/fetch";
4
5polyfillReadableStream();
6polyfillEncoding();
7polyfillFetch();
Finally, there’s a special option we’ll need to pass to our polyfilled
fetch
. Create anHttpLink
so we can set the following on our defaultfetchOptions
:
1const link = new HttpLink({
2 uri: "http://localhost:4000/graphql",
3 fetchOptions: {
4 reactNative: { textStreaming: true },
5 },
6});
Note: if you're still experiencing issues on Android after adding the polyfills above, there may be a library like Flipper that is intercepting requests during local development. Try commenting out
NetworkFlipperPlugin
in e.g.android/app/src/debug/java/com/<projectname>/ReactNativeFlipper.java
, or running your app in release mode.
Now you're ready to use @defer
and/or multipart subscriptions over HTTP in your React Native app!
Troubleshooting
Uncaught Error: Cannot read property 'prototype' of undefined
, or similar Metro build error when importing from@apollo/client
This is due to the way the Metro bundler supports .cjs
and .mjs
files: it requires additional configuration to implicitly resolve files with these extensions, so import { ApolloClient, InMemoryCache } from '@apollo/client'
will result in an error. You can amend your import statement to e.g. import { ApolloClient, InMemoryCache } from '@apollo/client/main.cjs'
, or you can install @expo/metro-config
and configure their implicit resolution via metro.config.js
in the root of your project:
1const { getDefaultConfig } = require('@expo/metro-config');
2
3const config = getDefaultConfig(__dirname);
4
5config.resolver.sourceExts.push(
6 'cjs'
7);
8
9module.exports = config;