Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

A plugin for graphql-code-generator to create fully typed React Hooks from GraphQL queries, mutations and subscriptions.

NotificationsYou must be signed in to change notification settings

pothos-dev/apollo-hooks-codegen

Repository files navigation

This is a plugin forgraphql-code-generator that generates fully typed React Hooks from queries, mutations and subscriptions in.graphql files.

Getting started

Installation

npm i -D graphql-code-generator apollo-hooks-codegen

Writing Queries

Unless traditional Apollo usage, we're actually writing all our queries, mutations and subscriptions inside a dedicated .graphql file:

# /src/graphql/todos.graphqlfragmentTodoPartsonTodoItem {idtitleisDone}querygetAllTodos {todoItems {...TodoParts  }}subscriptionsubscribeTodos {newTodoItem:subscribeTodoItems {...TodoParts  }}mutationcreateTodo($todoItem:TodoItemInput!) {createTodoItem(todoItem:$todoItem) {id  }}

Setting up codegen

The graphql-code-generator is best configured via acodegen.yml file.

Here we tell the generator to create a./src/graphql/index.ts file using apollo-hooks-codegen.

# codegen.ymlschema:http://localhost:4000documents:./src/graphql/*.graphqloverwrite:truegenerates:./src/graphql/index.ts:    -apollo-hooks-codegen

After creating the file, we just run:npx gql-gen

Configuring ApolloClient

The hooks need access to an instance ofApolloClient. If you previously used Apollo, you probably already have this set up, otherwise, refer to theGet started guide.

The code generator created an ApolloHooksProvider, which we have to set up at the root of our app:

import{ApolloHooksProvider}from'./src/graphql'constapolloClient=newApolloClient({/* ApolloClient configuration here */})functionAppWithApollo(){return(<ApolloHooksProviderapolloClient={apolloClient}><App/></ApolloHooksProvider>)}

After all of this is done, we can now start using the generated hooks.

Usage

Every document (query,mutation,subscription orfragment) in the .graphql file generated a Typescript function of the same name.

Each function takes an optional argument, which contains additional options. The configured document is then passed to one of the provided hooks:

Queries

useQuery useswatchQuery under the hood, so the component will re-render automatically if the queried data changes in Apollo's cache for any reason.

import{useQuery,getAllTodos}from'./src/graphql'functionTodoList(){constqueryResult=useQuery(getAllTodos({fetchPolicy:'cache-first'}))// get access to loading and error state of the queryif(queryResult.loading)return<p>Loading...</p>if(queryResult.error)return<p>Error</p>// data is null during loading and in case of error, but can be expected to be non-null otherwiseconsttodoItems=queryResult.data!.todoItems// the compiler knows about which fields are available on todoItemsreturn(<ul>{todoItems.map(item=>(<likey={item.id}>{item.title}</li>))}</ul>)}

Mutations

useMutation creates a function which executes the configured mutation and returns the result as a Promise.

import{useMutation,createTodo}from'./src/graphql'functionAddTodoButton(){constmutate=useMutation(createTodo({// options can be passed directly during configuration, like with useQuery.// alternatively, you can pass the options object later when calling the mutate functionvariables:{todoItem:{title:'Finish this button component...'},},}))return(<buttononClick={()=>{mutate().then(console.log)}}>      Click me!</button>)}

Subscriptions

Subscriptions require additional work when setting up ApolloClient, seehere.

import{useSubscription,subscribeTodos}from'./src/graphql'functionTodoItemTicker(){constsub=useSubscription(subscribeTodos())// If we did not receive a subscription event yet, the value is nullif(sub==null)returnnullreturn<p>Latest Todo:{sub.newTodoItem.title}</p>}

Often, you want to send a query to get some data, and create a subscription to be called back whenever the data changes on server. You can use this helper function to do both in one:

import{useQuery,getAllTodos}from'./src/graphql'functionTodoList(){constqueryResult=useQueryWithSubscription(getAllTodos(),// the initial querysubscribeTodos(),// the subscription(queryData,subData)=>({// Update the query data here with the latest data from the subscriptiontodoItems:[...queryData.todoItems,subData.newTodoItem],}))// loading and error state are taken only from the queryif(queryResult.loading)return<p>Loading...</p>if(queryResult.error)return<p>Error</p>consttodoItems=queryResult.data!.todoItemsreturn(<ul>{todoItems.map(item=>(<likey={item.id}>{item.title}</li>))}</ul>)}

Types

A key feature of GraphQL is the possibility to fetch as many or as few properties of an object as is needed for a particular view. For this reason, it is difficult to assume a specific interface for any GraphQL type.

This library generates named interfaces for every selection of fields in a query. For example, given the above mutation:

mutationcreateTodo($todoItem:TodoItemInput!) {createTodoItem(todoItem:$todoItem) {id  }}

the following types are generated:

// TodoItemInputtypeTodoItemInput={title:TodoItemInput_titledescription?:Nullable<TodoItemInput_description>dueDate?:Nullable<TodoItemInput_dueDate>}typeTodoItemInput_title=stringtypeTodoItemInput_description=stringtypeTodoItemInput_dueDate=any// createTodo() mutationtypecreateTodo_variables={todoItem:createTodo_variables_todoItem}typecreateTodo_variables_todoItem=TodoItemInputtypecreateTodo_data={createTodoItem:createTodo_data_createTodoItem}typecreateTodo_data_createTodoItem={id:createTodo_data_createTodoItem_id}typecreateTodo_data_createTodoItem_id=string

So it is easy to specify the type of the variables or result (data) of a query or mutation, or any subselection of those.

If you want to re-use a type, I suggest to use named fragments, which create types of the same name as the fragment:

fragmentTodoPartsonTodoItem {idtitleisDone}

produces:

typeTodoParts={id:TodoParts_idtitle:TodoParts_titleisDone:TodoParts_isDone}typeTodoParts_id=stringtypeTodoParts_title=stringtypeTodoParts_isDone=boolean

Generator Options

You can specify some options in the codegen.yml:

schema:http://localhost:4000documents:./src/graphql/*.graphqloverwrite:truegenerates:./src/graphql/index.ts:    -apollo-hooks-codegen# Options here:idType:any# The Typescript type generated for GraphQL's "ID" type (defaults to string)scalarTypes:# The Typescript types generated for custom scalar types in the GraphQL schema (defaults to any)JSON:stringUTCDate:unknown

Future Work

  • Suspense support
  • Default values

About

A plugin for graphql-code-generator to create fully typed React Hooks from GraphQL queries, mutations and subscriptions.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors2

  •  
  •  

[8]ページ先頭

©2009-2025 Movatter.jp