TypeScript Consumer¶
Preface¶
This guide will explain how to fetch data from a GraphQL endpoint and map the response to a TypeScript model using Relay.
Info
Refer to the Relay Docs to learn more.
We will cover:
- Setting up the Relay Environment in Setup Relay Environment
- Generating the TypeScipt types with Relay in Generate TypeScript Types
- Fetching data using Relay in Fetch Data Using Relay
- Mapping the response to TypeScript types in Mapping the response
Alternative Options
If you are looking for alternative GraphQL clients, you may consider:
graffle
for simpler setupApollo Client
for more featuresTypeGraphQL
if you require decorators and more advanced GraphQL server setups
Dependencies¶
This guide assumes you have already set up Relay in your project. Relay is highly integrated with React, so you’ll also need the following packages:
react-relay
for React integration with Relayrelay-runtime
for core Relay functionalitybabel-plugin-relay
for compiling Relay queries
Setup Relay Environment¶
We initially must set up a Relay environment which allows Relay to access the GraphQL endpoint.
In the root of src
we create a RelayEnvironment.ts
. In this file we are setup up a Relay environment for making GraphQL requests.
The fetchFn
function abstracts the networking stack, sending a POST
request to the GraphQL endpoint with the query and variables while also allowing for extensions like rate limiting or custom error handling as needed.
The createRelayEnvironment
function initializes the Relay environment by combining the network layer (responsible for fetching data) and the store (which caches the data).
RelayEnvironment.ts
import {
Environment,
Network,
RecordSource,
Store,
FetchFunction,
} from "relay-runtime";
const HTTP_ENDPOINT = "http://127.0.0.1:8000/graphql"; // assuming you are running any of the services from how to guides
const fetchFn: FetchFunction = async (request, variables) => {
const response = await fetch(HTTP_ENDPOINT, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
query: request.text,
variables,
}),
});
return await response.json();
};
function createRelayEnvironment() {
return new Environment({
network: Network.create(fetchFn),
store: new Store(new RecordSource()),
});
}
export const RelayEnvironment = createRelayEnvironment();
Info
Refer to the Relay Environment Docs to learn more.
Generate TypeScript Types¶
Relay generates TypeScript types automatically for your queries, based on the GraphQL schema. For example, if you are querying a Person type form the GraphQL schema, Relay will generate types for you.
query PersonQuery {
person {
id
firstName
lastName
}
}
Relay will automatically generate a TypeScript type for this Query when you run the Relay compiler.
// __generated__/PersonQuery.graphql.ts
export interface PersonQuery {
person: {
id: string;
firstName: string;
lastName: string;
} | null;
}
Fetch Data Using Relay¶
In Relay, we define our GraphQL queries within components using the useLazyLoadQuery
or useFragment
hooks. Relay then fetches and manages data for you.
To fetch data, we define a query in our component and use Relay's useLazyLoadQuery
hook to execute it. The query is defined using the GraphQL tag provided by babel-plugin-relay
.
Fetch Data with Relay
import { graphql, useLazyLoadQuery } from "react-relay";
import { PersonQuery } from './__generated__/PersonQuery.graphql'; // generated by relay compiler
const PersonComponent = () => {
const data = useLazyLoadQuery<PersonQuery>(
graphql`
query PersonQuery {
person {
id
firstName
lastName
}
}
`,
{}
);
if (!data.person) {
return <div>Loading...</div>;
}
return (
<div>
<h1>{data.person.firstName} {data.person.lastName}</h1>
</div>
);
};
export default PersonComponent;
Mapping the Response¶
With Relay, we don't need to manually map the response to TypeScript models as the Relay handles this internally and generates types for each query. Relay will ensure the data conforms to the types defined in your GraphQL schema. It will map the response to the PersonQuery type and ensure that your TypeScript code only access the fields that match the GraphQL schema, such as id, firstName and lastName. If the GraphQL schema changes or if there's a mismatch in types, Relay will flag it during compilation giving type safety.
If the Python graphQL service is running, PersonComponent
should render:
foo bar