Skip to content

Commit

Permalink
docs: dedicated react-query guide (#10002)
Browse files Browse the repository at this point in the history
* docs: dedicated react-query guide

* Apply suggestions from code review

Co-authored-by: Saihajpreet Singh <saihajpreet.singh@gmail.com>

---------

Co-authored-by: Saihajpreet Singh <saihajpreet.singh@gmail.com>
  • Loading branch information
n1ru4l and saihaj authored Jul 28, 2024
1 parent b9006ec commit d0cdb8f
Show file tree
Hide file tree
Showing 3 changed files with 263 additions and 11 deletions.
1 change: 1 addition & 0 deletions website/src/pages/docs/guides/_meta.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export default {
'react-vue': 'React / Vue',
'vanilla-typescript': 'Vanilla TypeScript',
'react-query': 'React Query',
angular: 'Angular',
svelte: 'Svelte / Kit',
'flutter-freezed': 'Dart/Flutter',
Expand Down
254 changes: 254 additions & 0 deletions website/src/pages/docs/guides/react-query.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@
---
description: Execute GraphQL queries type-safe in React Query with GraphQL Code Generator.
---

# GraphQL Codegen with React Query

In this guide, we will learn how to use the GraphQL Code Generator client preset with React Query to generate type-safe operations and wire it up to a GraphQL server that supports the
GraphQL over HTTP protocol.

## Prerequisites

For this guide, we assume that you are querying your GraphQL server from within a Browser environment.
So you already have your Vite, Next.js, Node.js or any other vanilla
project with TypeScript setup.

We are going to use the public [Star Wars GraphQL API](https://swapi-graphql.netlify.app/) as our
GraphQL endpoint.

## Setting up GraphQL Code Generator

The GraphQL Code Generator client preset is the preferred and built-in way to generate type-safe
operations for any GraphQL client library and also vanilla JavaScript.

To get started, install the following dependencies

- **`@graphql-codegen/cli`**: Codegen CLI for running code generation
- **`@parcel/watcher`**: Enable watch mode for the codegen CLI
- **`@graphql-codegen/schema-ast`**: Plugin for generating the schema file from the GraphQL API
endpoint (optional if you already have a schema file)
- **`@0no-co/graphqlsp`**: TypeScript language server plugin for GraphQL auto-complete (optional)

Feel free to omit the optional dependencies if you don't need them.

```sh npm2yarn
npm install --save-dev @graphql-codegen/cli @parcel/watcher
npm install --save-dev @graphql-codegen/schema-ast
npm install --save-dev @0no-co/graphqlsp
```

After that, we can create a `codegen.ts` file in the root of our project with the following
contents:

```typescript filename="GraphQL Codegen Configuration"
import type { CodegenConfig } from '@graphql-codegen/cli'

const config: CodegenConfig = {
schema: 'https://swapi-graphql.netlify.app/.netlify/functions/index',
documents: ['src/**/*.tsx'],
ignoreNoDocuments: true,
generates: {
'./src/graphql/': {
preset: 'client',
config: {
documentMode: 'string'
}
},
'./schema.graphql': {
plugins: ['schema-ast'],
config: {
includeDirectives: true
}
}
}
}

export default config
```

Next, we adjust our `tsconfig.json` to load `@0no-co/graphqlsp`.

```json filename="tsconfig.json"
{
"compilerOptions": {
"plugins": [
{
"name": "@0no-co/graphqlsp",
"schema": "./schema.graphql"
}
]
}
}
```

Finally, we also need to prompt Visual Studio Code to use the local TypeScript version by creating a
`.vscode/settings.json` file with the following contents:

```json filename=".vscode/settings.json"
{
"typescript.tsdk": "node_modules/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true
}
```

## Running the Code Generator

Now we can run the following command to generate the `schema.graphql` file and the GraphQL Code
Generator client code. **Note:** We are not yet writing GraphQL operations in our codebase, we just
generate the client boilerplate code.

```sh filename="Run GraphQL Code Generator"
npx graphql-codegen --config codegen.ts
```

After running the command, you should see a new `schema.graphql` file in the root of your project
and a new folder `src/graphql` with the generated client code.

You almost never need to touch the files within `src/graphql` as they are generated and overwritten
by GraphQL Code generator.

We will now use the generated client code to write our type-safe GraphQL operations.

## Writing GraphQL Operations

Let's start GraphQL Code Generator in watch mode to generate the client code whenever we write our
code.

```sh filename="Run GraphQL Code Generator in watch mode"
npx graphql-codegen --config codegen.ts --watch
```

Next within any file in our projects `src` folder, we will import the `graphql` function from within
`src/graphql`.

```typescript filename="src/index.ts"
import { graphql } from './graphql'
```

This function allows us to define a GraphQL operation.

Thanks to the TypeScript GraphQL LSP plugin, we get auto-complete for our GraphQL operations while
writing them.

![GraphQLSP in Action, giving us auto-complete on the selection set](/assets/pages/docs/guides/vanilla-typescript/graphql-lsp-autocomplete.png)

With that, we will write a simple query operation to get the total count of people in the Star Wars
universe.

```typescript filename="src/index.ts"
import { graphql } from './graphql'

const PeopleCountQuery = graphql(`
query PeopleCount {
allPeople {
totalCount
}
}
`)
```

As we now save the file in our editor, the GraphQL Code Generator will generate the corresponding
types, and as you hover over the `PeopleCountQuery` variable, you will see the following:

![GraphQLSP in Action, giving us auto-complete on the selection set](/assets/pages/docs/guides/vanilla-typescript/typescript-typed-result.png)

`TypedDocumentString` is a container type that holds the query operation string and also the
TypeScript type for that operations response.

We can now leverage this to build a type-safe function that executes the GraphQL operation against
our GraphQL server.

## Type-Safe GraphQL Operation Execution

We can build a simple wrapper around `fetch` that takes a `TypedDocumentString` parameter and
returns a typed response.

```typescript filename="src/graphql/execute.ts"
import type { TypedDocumentString } from './graphql'

export async function execute<TResult, TVariables>(
query: TypedDocumentString<TResult, TVariables>,
...[variables]: TVariables extends Record<string, never> ? [] : [TVariables]
) {
const response = await fetch('https://swapi-graphql.netlify.app/.netlify/functions/index', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Accept: 'application/graphql-response+json'
},
body: JSON.stringify({
query: document,
variables
})
})

if (!response.ok) {
throw new Error('Network response was not ok')
}

return response.json() as TResult
}
```

We can now use this function to execute our `PeopleCountQuery` operation.

```typescript filename="src/index.ts"
import { graphql } from './graphql'
import { execute } from './graphql/execute'

const PeopleCountQuery = graphql(`
query PeopleCount {
allPeople {
totalCount
}
}
`)

execute(PeopleCountQuery).then(data => {
console.log(data)
})
```

When we now hover over the `data` parameter in the `then` callback, we can see that the response is
fully typed.

![Fully typed GraphQL execution result](/assets/pages/docs/guides/vanilla-typescript/typescript-typed-result.png)

## Executing Query Operations with React Query

We can now leverage the `execute` function to execute our GraphQL operations with React Query.

```tsx filename="Example usage of executing a Query Operation with React Query"
import { useQuery } from '@tanstack/react-query'
import { graphql } from './graphql'
import { execute } from './graphql/execute'

const PeopleCountQuery = graphql(`
query PeopleCount {
allPeople {
totalCount
}
}
`)

function App() {
const { data } = useQuery({
queryKey: ['films'],
queryFn: () => execute(PeopleCountQuery)
})

return <div>There are {data?.allPeople.totalCount} people</div>
}
```

## Conclusion

In this article, we learned how to use GraphQL Code Generator preset with React Query.

If you want to learn more about GraphQL Code Generator, check out the
[client preset documentation](/plugins/presets/preset-client).
E.g. you want to reduce bundle size by using the
[client preset babel plugin](/plugins/presets/preset-client#reducing-bundle-size)
or enable
[persisted documents](/plugins/presets/preset-client#persisted-documents)
in production for security and performance reasons.
19 changes: 8 additions & 11 deletions website/src/pages/docs/guides/vanilla-typescript.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
description: Execute GraphQL queries type-safe in vanilla TypeScript with GraphQL Code Generator.
---

# Guide: Vanilla TypeScript
# GraphQL Codegen with Vanilla TypeScript

GraphQL client libraries such as Apollo Client, Relay, and Urql are popular choices that allows
building powerful features for querying but come with a few drawbacks:
Expand All @@ -19,9 +19,7 @@ TypeScript to generate type-safe operations and wire it up to a GraphQL server t
GraphQL over HTTP protocol.

This approach is framework/runtime (React, Vue, Svelte, Node.js, Bun) agnostic and the function for
executing GraphQL operations will be a simple `fetch` wrapper that can be integrated with popular
solutions such as [TanStack Query (React Query)](https://tanstack.com/query) or
[SWR](https://swr.vercel.app/).
executing GraphQL operations will be a simple Type-Safe `fetch` wrapper.

## Prerequisites

Expand All @@ -34,7 +32,7 @@ This guide will work on any JavaScript environment that supports `fetch` API.
We are going to use the public [Star Wars GraphQL API](https://swapi-graphql.netlify.app/) as our
GraphQL endpoint.

## Setting up GraphQL Code Generator Client preset
## Setting up GraphQL Code Generator

The GraphQL Code Generator client preset is the preferred and built-in way to generate type-safe
operations for any GraphQL client library and also vanilla JavaScript.
Expand All @@ -43,15 +41,14 @@ To get started, install the following dependencies

- **`@graphql-codegen/cli`**: Codegen CLI for running code generation
- **`@parcel/watcher`**: Enable watch mode for the codegen CLI
- **`@graphql-codegen/client-preset`**: Client preset for generating type-safe operations
- **`@graphql-codegen/schema-ast`**: Plugin for generating the schema file from the GraphQL API
endpoint (optional if you already have a schema file)
- **`@0no-co/graphqlsp`**: TypeScript language server plugin for GraphQL auto-complete (optional)

Feel free to omit the optional dependencies if you don't need them.

```sh npm2yarn
npm install --save-dev @graphql-codegen/cli @parcel/watcher @graphql-codegen/client-preset
npm install --save-dev @graphql-codegen/cli @parcel/watcher
npm install --save-dev @graphql-codegen/schema-ast
npm install --save-dev @0no-co/graphqlsp
```
Expand Down Expand Up @@ -121,12 +118,12 @@ npx graphql-codegen --config codegen.ts
```

After running the command, you should see a new `schema.graphql` file in the root of your project
and a new folder `src/graphql` with the generated client preset code.
and a new folder `src/graphql` with the generated client code.

You almost never need to touch the files within `src/graphql` as they are generated and overwritten
by GraphQL Code generator.

We will now use the generated client preset code to write our type-safe GraphQL operations.
We will now use the generated client code to write our type-safe GraphQL operations.

## Writing GraphQL Operations

Expand Down Expand Up @@ -238,10 +235,10 @@ TypeScript project.

## Conclusion

In this article, we learned how to use the GraphQL Code Generator client preset with vanilla
In this article, we learned how to use GraphQL Code Generator with vanilla
TypeScript.

We set up the GraphQL Code Generator client preset and wrote a simple operation that is fully typed.
We set up the GraphQL Code Generator for clients and wrote a simple operation that is fully typed.

You could now integrate the `execute` function into
[TanStack Query (React Query)](https://tanstack.com/query) or SWR.
Expand Down

0 comments on commit d0cdb8f

Please sign in to comment.