- Notifications
You must be signed in to change notification settings - Fork4
pothos-dev/apollo-hooks-codegen
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
This is a plugin forgraphql-code-generator that generates fully typed React Hooks from queries, mutations and subscriptions in.graphql files.
npm i -D graphql-code-generator apollo-hooks-codegen
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 }}
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
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.
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:
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>)}
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 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>)}
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
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
- Suspense support
- Default values
About
A plugin for graphql-code-generator to create fully typed React Hooks from GraphQL queries, mutations and subscriptions.
Resources
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Releases
Packages0
Uh oh!
There was an error while loading.Please reload this page.
Contributors2
Uh oh!
There was an error while loading.Please reload this page.