GraphQL

With Apollo

Using pg_grapqhl with Apollo.

This guide will show you how to use pg_graphql with Apollo and GraphQL Code Generator for type-safe GraphQL queries in your React application.

Apollo Setup

Pre-requisites

  1. Follow the Apollo Getting Started Guide.
  2. Follow the GraphQL Code Generator Installation Guide.

Configuring GraphQL Code Generator

Modify your codegen.ts file to reflect the following:


_33
import type { CodegenConfig } from '@graphql-codegen/cli'
_33
import { addTypenameSelectionDocumentTransform } from '@graphql-codegen/client-preset'
_33
_33
const config: CodegenConfig = {
_33
schema: 'http://localhost:54321/graphql/v1', // Using the local endpoint, update if needed
_33
documents: 'src/**/*.tsx',
_33
overwrite: true,
_33
ignoreNoDocuments: true,
_33
generates: {
_33
'src/gql/': {
_33
preset: 'client',
_33
documentTransforms: [addTypenameSelectionDocumentTransform],
_33
plugins: [],
_33
config: {
_33
scalars: {
_33
UUID: 'string',
_33
Date: 'string',
_33
Time: 'string',
_33
Datetime: 'string',
_33
JSON: 'string',
_33
BigInt: 'string',
_33
BigFloat: 'string',
_33
Opaque: 'any',
_33
},
_33
},
_33
},
_33
},
_33
hooks: {
_33
afterAllFileWrite: ['npm run prettier'], // optional
_33
},
_33
}
_33
_33
export default config

Configuring Apollo Client

This example uses Supabase for the GraphQL server, but pg_graphql can be used independently.


_58
import {
_58
ApolloClient,
_58
InMemoryCache,
_58
createHttpLink,
_58
defaultDataIdFromObject
_58
} from '@apollo/client'
_58
import { setContext } from '@apollo/client/link/context'
_58
import { relayStylePagination } from '@apollo/client/utilities'
_58
import supabase from './supabase'
_58
_58
const cache = new InMemoryCache({
_58
dataIdFromObject(responseObject) {
_58
if ('nodeId' in responseObject) {
_58
return `${responseObject.nodeId}`
_58
}
_58
_58
return defaultDataIdFromObject(responseObject)
_58
},
_58
possibleTypes: { Node: ['Todos'] } // optional, but useful to specify supertype-subtype relationships
_58
typePolicies: {
_58
Query: {
_58
fields: {
_58
todosCollection: relayStylePagination(), // example of paginating a collection
_58
node: {
_58
read(_, { args, toReference }) {
_58
const ref = toReference({
_58
nodeId: args?.nodeId,
_58
})
_58
_58
return ref
_58
},
_58
},
_58
},
_58
},
_58
},
_58
})
_58
_58
const httpLink = createHttpLink({
_58
uri: 'http://localhost:54321/graphql/v1',
_58
})
_58
_58
const authLink = setContext(async (_, { headers }) => {
_58
const token = (await supabase.auth.getSession()).data.session?.access_token
_58
_58
return {
_58
headers: {
_58
...headers,
_58
Authorization: token ? `Bearer ${token}` : '',
_58
},
_58
}
_58
})
_58
_58
const apolloClient = new ApolloClient({
_58
link: authLink.concat(httpLink),
_58
cache,
_58
})
_58
_58
export default apolloClient

  • typePolicies.Query.fields.node is also optional, but useful for reducing cache misses. Learn more about Redirecting to cached data.

Example Query


_46
import { useQuery } from '@apollo/client'
_46
import { graphql } from './gql'
_46
_46
const allTodosQueryDocument = graphql(/* GraphQL */ `
_46
query AllTodos($cursor: Cursor) {
_46
todosCollection(first: 10, after: $cursor) {
_46
edges {
_46
node {
_46
nodeId
_46
title
_46
}
_46
}
_46
pageInfo {
_46
endCursor
_46
hasNextPage
_46
}
_46
}
_46
}
_46
`)
_46
_46
const TodoList = () => {
_46
const { data, fetchMore } = useQuery(allTodosQueryDocument)
_46
_46
return (
_46
<>
_46
{data?.thingsCollection?.edges.map(({ node }) => (
_46
<Todo key={node.nodeId} title={node.title} />
_46
))}
_46
{data?.thingsCollection?.pageInfo.hasNextPage && (
_46
<Button
_46
onClick={() => {
_46
fetchMore({
_46
variables: {
_46
cursor: data?.thingsCollection?.pageInfo.endCursor,
_46
},
_46
})
_46
}}
_46
>
_46
Load More
_46
</Button>
_46
)}
_46
</>
_46
)
_46
}
_46
_46
export default TodoList