React with GraphQL — A better way

React and GraphQL — Single Apollo Client Instance with Multiple Servers

Motivation

Today in the era of distributed and agile workflows, it is crucial to maintain coordination between teams spread across geographies and resolve dependencies on time to keep developers unblocked. Recently, while working on a react application we faced issues while integrating GraphQL APIs that were managed by a different team. Sometimes the server was down or APIs were partially working. In order to keep things going at our end we needed some sort of fallback setup to mock GraphQL requests with dummy data.

  • Static JSON files from file system: This method uses fetch to load static files from local directory. While this approach can render the UI with required data but require lot if rework in component source code and unit tests whenever we need to switch between mock data(fetch) and actual API(useQuery hook). Also, static files can not handle decision making like actual resolvers.
  • Mirage JS: This is another solution to mock API requests but led to similar challenges as static files. No intelligence of resolvers and difference between nature of actual GraphQL requests and REST, which have single smart endpoint unlike REST.

Demo App

Assuming you are familiar about GraphQL basics, I’ll skip theories and jump straight into the implementation. The source code is available @git.

  1. App level: An env variable API_MOCK is used to decide the value of boolean request header mock. If true, queries are sent to mock server. This approach will control all queries in the application at one place . It will take one of three possible values: ‘ON’, ‘OFF’, ‘AUTO’. The last mode will automatically redirect to the fallback server in case main server throws error.
  2. Query level: The file queryMock.js keeps key value pairs to direct any particular query to a different server. Key should exactly match the query name in schema. Value is a boolean.

Apollo-Client setup

The client is initialised with apollo-link-http custom fetch option. All the requests to GraphQL server are intercepted at this level to decide the domain dynamically based on headers or query level mocks.

Custom fetch for apollo-link-http

Custom Hook — useQueryMod

This is a wrapper on top of useLazyHook provided by Apollo. It checks environment variable API_MOCK to set query header mock. It has same interface as useLazyQuery hook and handles redirection to mock server behind the scenes. The will ease the integration with existing applications with minimal source code changes. Another benefit of using a custom hook is the ease of unit testing because we can directly mock the custom hook module using jest and there is no need to wrap the test instance in Apollo Context. It is also possible to use fetchOptions property instead of headers to set custom properties in fetch. Refer Apollo docs for more details.

Add custom headers in query using context option

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store