Apollo GraphQL

👋 FYI, this note is over 6 months old. Some of the content may be out of date.
On this page

Queries Jump to heading

Queries docs

import gql from 'graphql-tag'

const GET_DOGS = gql`
{
dogs {
id
breed
}
}
`

useQuery hook Jump to heading

useQuery Docs

import { useQuery } from '@apollo/react-hooks'

const { data, loading, error } = useQuery(GET_DOGS)

// useQuery with a `variable`
const { data, loading, error } = useQuery(GET_DOG_PHOTO, {
variables: { breed },
})

Example component Jump to heading

const Dogs = ({ onDogSelected }) => {
const { data, loading, error } = useQuery(GET_DOGS)

if (loading) {
return <Loader />
}

if (error) {
return <p>Error {JSON.stringify(error, null, 2)}</p>
}

return (
<select name="dog" onChange={onDogSelected}>
{data.dogs.map((dog) => (
<option key={dog.id} value={dog.breed}>
{dog.breed}
</option>
))}
</select>
)
}

Mutations Jump to heading

Mutations docs

Queries enable clients to fetch data, but not to modify data. To enable clients to modify data, our schema needs to define some mutations.

useMutation hook Jump to heading

useMutation Docs

import { useMutation } from '@apollo/react-hooks'

const [addTodo, { data, loading, error }] = useMutation(ADD_TODO)

// usage
addTodo({ variables: { type: 'some value' } })

Example component Jump to heading

import gql from 'graphql-tag'
import { useMutation } from '@apollo/react-hooks'

const ADD_TODO = gql`
mutation AddTodo($type: String!) {
addTodo(type: $type) {
id
type
}
}
`


const AddTodo = () => {
let input
const [addTodo, { data }] = useMutation(ADD_TODO)

return (
<div>
<form
onSubmit=
{(e) => {
e.preventDefault()
addTodo({ variables: { type: input.value } })
input.value = ''
}}
>
<input
ref={(node) => {
input = node
}}

/>

<button type="submit">Add Todo</button>
</form>
</div>
)
}

Updating the cache Jump to heading

If a mutation modifies multiple entities, or if it creates or deletes entities, the Apollo Client cache is not automatically updated to reflect the result of the mutation. To resolve this, your call to useMutation can include an update function.

The purpose of an update function is to modify your cached data to match the modifications that a mutation makes to your back-end data. In the example in Executing a mutation, the update function for the ADD_TODO mutation should add the same item to our cached version of the to-do list.

const GET_TODOS = gql`
query GetTodos {
todos
}
`


const AddTodo = () => {
let input
const [addTodo] = useMutation(ADD_TODO, {
update(cache, { data: { addTodo } }) {
const { todos } = cache.readQuery({ query: GET_TODOS })
cache.writeQuery({
query: GET_TODOS,
data: { todos: todos.concat([addTodo]) },
})
},
})

return (
<div>
<form
onSubmit={(e) => {
e.preventDefault()
addTodo({ variables: { type: input.value } })
input.value = ''
}}
>
<input
ref={(node) => {
input = node
}}
/>
<button type="submit">Add Todo</button>
</form>
</div>
)
}

Fragments Jump to heading

Fragments docs

fragment NameParts on Person {
firstName
lastName
}

query GetPerson {
people(id: "7") {
...NameParts
avatar(size: LARGE)
}
}

Resolvers Jump to heading

Resolvers provide the instructions for turning a GraphQL operation (a query, mutation, or subscription) into data. They either return the same type of data we specify in our schema or a promise for that data.

Before we can start writing resolvers, we need to learn more about what a resolver function looks like. Resolver functions accept four arguments:

fieldName: (parent, args, context, info) => data
  • parent: An object that contains the result returned from the resolver on the parent type
  • args: An object that contains the arguments passed to the field
  • context: An object shared by all resolvers in a GraphQL operation. We use the context to contain per-request state such as authentication information and access our data sources.
  • info: Information about the execution state of the operation which should only be used in advanced cases

← Back home