Apollo GraphQL
On this page
Queries
import gql from 'graphql-tag'const GET_DOGS = gql`{dogs {idbreed}}`
useQuery hook
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
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
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
import { useMutation } from '@apollo/react-hooks'const [addTodo, { data, loading, error }] = useMutation(ADD_TODO)// usageaddTodo({ variables: { type: 'some value' } })
Example component
import gql from 'graphql-tag'import { useMutation } from '@apollo/react-hooks'const ADD_TODO = gql`mutation AddTodo($type: String!) {addTodo(type: $type) {idtype}}`const AddTodo = () => {let inputconst [addTodo, { data }] = useMutation(ADD_TODO)return (<div><formonSubmit={(e) => {e.preventDefault()addTodo({ variables: { type: input.value } })input.value = ''}}><inputref={(node) => {input = node}}/><button type="submit">Add Todo</button></form></div>)}
Updating the cache
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 inputconst [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><formonSubmit={(e) => {e.preventDefault()addTodo({ variables: { type: input.value } })input.value = ''}}><inputref={(node) => {input = node}}/><button type="submit">Add Todo</button></form></div>)}
Fragments
fragment NameParts on Person {firstNamelastName}query GetPerson {people(id: "7") {...NamePartsavatar(size: LARGE)}}
Resolvers
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 typeargs
: An object that contains the arguments passed to the fieldcontext
: 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