This is a public journal that would include stuff I think are necessary for me to remember.
Previously I have been tweeting about it, but then Twitter is a private owned platform and anything could happen to my account.
Now onto the good stuff:
- On the Client side, the
useQuery
hook returns an object with 3 useful properties. They are destructured. The first, loading, indicates whether the query has completed and results have been returned. The second, error is an object that contains any errors that the operation has thrown. The third, data contains the results of the query after it has completed.
To set variables in our Query, we declare them in the second parameter of the useQuery
hook, inside the options object.
Code Example using React JS:
import { useQuery, gql } from '@apollo/client'
export const GET_TRACK = gql`
query getTrack($trackId: ID!) {
track(id: $trackId) {
id
title
author {
id
name
photo
}
thumbnail
length
modulesCount
numberOfViews
modules {
id
title
length
}
description
}
}
`
const Track = (props) => {
const {loading, error, data} = useQuery(GET_TRACK,{
variables: {prop.id}
})
return(
//render UI
)
}
- I had to create a schema for the module type for a track, get the data from the dataSource and structure the resolver to return the required field.
I'd say the hardest part was the resolver but with some thinking, I was able to figure it out.
What I learned is that: Your resolver function should follow your schema defined. Not just willy nilly stuff.
First the schema:
type Module {
id: ID!
"the title of the particular module"
title: String!
length: Int
"the url of the particular module"
videoUrl: String!
"the content of the particular module"
content: String!
}
and then defining the Query that would return the required module when supplied with an argument
type Query {
"Query to get tracks array for the homepage grid"
tracksForHome: [Track!]!
"a track id would return a details about a specific track"
track(id: ID!): Track
"a module would return details about a specific module"
module(id: ID!): Module!
}
the dataSource for the current application is a RESTAPI so I had to use a method to get the module from that.
I did that by writing:
getModule(moduleId) {
return this.get(`module/${moduleId}`)
}
and finally the resolver. This part got me so confused because of
- the parent parameter
- the args parameter
I still haven't gotten the grasp of the arguments resolver functions need so it took me a bit to think through my Schema and how the Query is going to be structured.
After that, I solved it and wrote the following resolver function
module: (_, { id }, { dataSources }) => {
return dataSources.trackAPI.getModule(id)
}
//nested in a query parent
I just read about Mutations and how they can serve as entry points into our GraphQL Api especially if we need to write data to our server.
A fill in the gap exercise on the Apollo website resulted in this helpful paragraph.
"Queries and Mutations are both types of GraphQL operations
. Queries are read
operations that always retrieve
data. Mutations are write
operations that always modify
data. Similar to Query
fields, fields of the Mutation
type are also entry points
into a GraphQL API."
Mutations can be easy or complex depending on the return value required and the fields being modified.
For example, a simple mutation can just have one return value. Like this:
type Mutation{
addSpaceCat(name: String!): SpaceCat
}
This is because once we call the addSpaceCat mutation, we want the client to get the updated value of the SpaceCat we just mutated.
Sometimes, though, one mutation should return multiple values.
type Mutation{
assignMission(missionId: ID!, spaceCatId: ID!): ???
}
//what should we return
and so because we need to return both, we need to create a new type. This type would include
-
code
: anInt
that refers to the status of the response similar to an HTTP status code. -
success
: aBoolean
flag that indicates whether all the updates the mutation was responsible for succedded. -
message
: aString
to display information about the result of the mutation on the client side. This is useful for us if the mutation is only, well partially successful and a generic error message won't tell the whole story.
with that, we then create a new type for our mutation respose.
type AssignMissionResponse {
code: Int!
Success: Boolean!
message: String!
spacecat: Spacecat
mission: Mission
}
Regarding GraphQL Mutation:
We use hooks to send requests to our GraphQL API from a React client. To send a mutation, we use the useMutation
hook. This returns an array
where the first element is the mutate function
used to trigger the mutation. The second element is an object with more information about the mutation, such as loading
, error
and data
. This hook takes in a GraphQL operation
as the first parameter. It also takes in an options
object as the second parameter, where properties like variables
are set.
Top comments (0)