Tooling your typescript create react app to work with GraphQL

I’m going to assume you’ve already bootstrapped your app with the typescript template, create-react-app.
In this article, we are going to learn how to tool your app development process to use GraphQL with a demo weather app by:
- Using consistent filename to hold our queries, mutations, and fragments.
- Generating typescript types (interfaces, enums, etc.) from a GraphQL server with graphql-codegen.
- Generating custom React hooks for each query and mutation using Apollo client.
- Adding a watch script to run graphql-codegen process on modification of our GraphQL queries.
- Adding a Graphql explorer to explore server types, queries, and mutations.
Prerequisites
Before we dive in, we need to add a basic GraphQL package which is required by the other dependencies we are going to make use of.
yarn add graphql
Initializing our project with Graphql-codegen
Graphql-codegen is a tool for generating code based on a GraphQL schema and GraphQL operations. Read more here.
We are going to use this to achieve most of the things this post is going to cover. Let’s add graphql-codegen as a dev dependency to our app:
yarn add -D @graphql-codegen/clior npm install -D @graphql-codegen/cli
We are going to use the above CLI to initialize our project, which uses different questions to set up your project.
yarn graphql-codegen initor npx graphql-codegen init
The above will show up with some questions which I will outline below with their corresponding answers:
? What type of application are you building? Application built with React
? Where is your schema?: http://localhost:4000
? Where are your operations and fragments?: src/**/*/queries.ts
? Pick plugins: TypeScript React Apollo (typed components and HOCs)
? Where to write the output: src/generated/graphql.tsx
? Do you want to generate an introspection file? Yes
? How to name the config file? codegen.yml
? What script in package.json should run the codegen? codegen
schema
location will be updated to use our graphql server later on.src/**/*/queries.ts
is going to hold our queries that will eventually be converted to standard GraphQL AST.- We need the introspection file (
graphql.schema.json
) for setting up our local GraphQL explorer if the GraphQL server doesn’t have one for you to explore queries, mutations, and response types.
After running graphql-codegen init function, you should have ./codegen.yml
overwrite: true
schema: ""
documents: "src/**/*/queries.ts"
generates:
src/generated/graphql.tsx:
plugins:
- "typescript"
- "typescript-operations"
- "typescript-react-apollo"
./graphql.schema.json:
plugins:
- "introspection"
And your package.json
scripts section should have:
"codegen": "graphql-codegen --config codegen.yml"
Generating typescript types (interfaces, enums, etc.) from a GraphQL server
We are going to be using https://graphql-weather-api.herokuapp.com/
as our demo GraphQL server. If you need more public GraphQL APIs to play with, you can check the list here.
Open codegen.yml
and update the schema
field to:
schema: "https://graphql-weather-api.herokuapp.com/
Before we try any of the GraphQL query provided by our server, let’s add a dependency that will help convert our queries to standard GraphQL AST and also generate custom react hooks (next section):
yarn add @apollo/client
Let’s test run our process by creating ./src/components/Weather/queries.ts
and adding the below query to retrieve weather report for a city:
import { gql } from '@apollo/client';export const GET_CITY_BY_NAME = gql`
query GetCityByName($name: String!) {
getCityByName(name: $name) {
id
name
country
weather {
summary {
title
description
icon
}
temperature {
actual
feelsLike
min
max
}
}
}
}
`;
Run the code below on your terminal:
yarn codegen
This should add two new files:
generated/graphql.tsx
which should contain all the schema types from our server.graphql.schema.json
which is generated by theintrospection
plugin we mentioned during initialization.
Generating custom react hooks for each query and mutation using Apollo client
Before we use our GetCityByName
, let’s enable custom React hooks for all mutations and queries that support typings for response fields and variables.
We are going to extend our codegen.yml
generates
configuration to support hooks creation for mutations/queries. Open codegen.yml
and update it with:
overwrite: true
schema: "https://graphql-weather-api.herokuapp.com/"
documents: "src/**/*/queries.ts"
generates:
src/generated/graphql.tsx:
plugins:
- "typescript"
- "typescript-operations"
- "typescript-react-apollo"
config:
withHooks: true
./graphql.schema.json:
plugins:
- "introspection"
withHooks
set to true
so we should be able to re-run yarn codegen
to see our custom react hooks added to our generated/graphql.tsx
.
In order to start using the generated hooks and types in our app, we need to wrap the root app component in <ApolloProvider>
like so:
...
import {
ApolloProvider,
HttpLink,
ApolloClient,
InMemoryCache,
} from "@apollo/client";const graphQLink = new HttpLink({
uri: "https://graphql-weather-api.herokuapp.com/",
});const cache = new InMemoryCache();const client = new ApolloClient({
link: graphQLink,
cache,
credentials: "include",
resolvers: {},
});ReactDOM.render(
<React.StrictMode>
<ApolloProvider client={client}>
<App />
</ApolloProvider>
</React.StrictMode>,
document.getElementById("root")
);...
This simply inits our app with apollo client and points to our GraphQL server. You can read more about initializing your app with Apollo client here.
We can now move on to using our generated custom react hooks to retrieve weather information. Add a new file to our weather component folder, ../src/components/Weather/index.tsx
, with the following codes:
Observe how, instead of using useQuery
which comes with no types, we used useGetCityByNameQuery
which is typed with the fields specified on our queries.ts
for both variables and response. It also supports the generation of lazy queries too e.g. useGetCityByNameLazyQuery
which works the same way a useQueryLazy
does. Read more about apollo client Hooks here.

Import the Weather
component into your App.tsx
.
Our app should be up and running when you run this next command:
yarn codegenyarn start

Adding a watch script to run the graphql-codegen process on modification of our GraphQL queries
From the last step, we have to stop our create React script local dev server to run codegen
again before starting the app. We are going to run the process in parallel with the Create React App start script using npm-run-all. Let’s install dependency:
yarn add -D npm-run-all
Open your package.json
and add the following scripts:
...
"scripts": {
"start:react": "react-scripts start",
"codegen:watch": "graphql-codegen --config codegen.yml --watch",
"start":"run-p codegen:watch start:react",
"codegen": "graphql-codegen --config codegen.yml",
... },
...
What we have done is add the --watch
flag to graphql-codegen
CLI to watch for changes in src/**/*/queries.ts
which was specified in our codegen.yml
. We moved the oldstart
script to start:watch
then updated our start
with npm-run-all
run-p
which is to run in parallel codegen
in watch mode and start the react app local dev server.
yarn start

Adding a Graphql explorer to explore server types, queries, and mutations
Lastly, let’s add a GraphQL explorer to easily see which queries and mutations are available for us to use, and the required parameters or allow fields we can send or retrieve respectively.
We are going to make use of the following dev dependencies which allow us to run a local node server to view our GraphQL explorer:
yarn add -D express express-graphql @graphql-tools/load @graphql-tools/json-file-loader
Add a new file server.js
to your root directory with the code below:
This server code simply relies on the introspection
plugin we added to our codegen.yml
; it loads the schema
using a JsonFileLoader
since we are using ./graphql.schema.json
(for more loaders, see here).
The loader should resolve with a schema that is compatible with our express-graphql middleware, and then serve our content with express on route /graphql
.
Now, open package.json
and add this script to run our server.js
:
...
"scripts": {
...
"graphql": "npm run codegen && node server.js"
},
...
What we have done is made sure that we have our introspection
file ready by running codegen
before running our server. Open your terminal and run:
yarn graphql
Our explorer should be served in http://localhost:4000/graphql
:

I personally add the
./graphql.schema.json
to.gitignore
since it will always be generated when your app is started.
Conclusion
I hope you have found this article helpful. Please see below for some additional tips, and feel free to leave feedback or questions in the comments section!
If you lint your project with ESLint, there’s a codegen plugin that adds custom code, imports, comments, and more to your output file. We can use it to add /* eslint-disable */
to the top of src/generated/graphql.tsx
like so:
yarn add -D @graphql-codegen/add
Open codegen.yml
and add the add
plugin under our output file plugins:
...
generates:
src/generated/graphql.tsx:
plugins:
- add:
content: "/* eslint-disable */"
- "typescript"
- "typescript-operations"
...