Add notes from Apollo GraphQL courses
This commit is contained in:
		
							parent
							
								
									2da598d3d3
								
							
						
					
					
						commit
						05a6d17a8e
					
				
					 4 changed files with 245 additions and 4 deletions
				
			
		
							
								
								
									
										88
									
								
								Databases/GraphQL/Apollo/Apollo_Client.md
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								Databases/GraphQL/Apollo/Apollo_Client.md
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,88 @@
 | 
			
		|||
---
 | 
			
		||||
title: Apollo Client
 | 
			
		||||
categories:
 | 
			
		||||
  - Databases
 | 
			
		||||
tags: [graph-ql, apollo]
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
# Apollo Client
 | 
			
		||||
 | 
			
		||||
Apollo Client is the client-side counterpart to [Apollo Server](/Databases/GraphQL/Apollo/Apollo_Server.md). We use it for managing queries and mutations from the frontend to our Apollo GraphQL server. It is specifically designed to work with React.
 | 
			
		||||
 | 
			
		||||
## Initializing the client
 | 
			
		||||
 | 
			
		||||
We initialise the client and set-up in memory caching to reduce network requests:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
const client = new ApolloClient({
 | 
			
		||||
  uri: "http://localhost:4000",
 | 
			
		||||
  cache: new InMemoryCache(),
 | 
			
		||||
});
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
> The uri property must match the location of our Apollo server.
 | 
			
		||||
 | 
			
		||||
## Utilising the provider
 | 
			
		||||
 | 
			
		||||
Apollo Provides a top level application context that we can wrap our React app in. This will provide access to the client object from anywhere within the app, eg:
 | 
			
		||||
 | 
			
		||||
```jsx
 | 
			
		||||
ReactDOM.render(
 | 
			
		||||
  <ApolloProvider client={client}>
 | 
			
		||||
    <GlobalStyles />
 | 
			
		||||
    <Pages />
 | 
			
		||||
  </ApolloProvider>,
 | 
			
		||||
  document.getElementById("root")
 | 
			
		||||
);
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Running a query
 | 
			
		||||
 | 
			
		||||
### Query constants
 | 
			
		||||
 | 
			
		||||
To run a query against our server we must define a query contant first. We use a `gql` literal again:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
import { gql } from "@apollo/client";
 | 
			
		||||
const TRACKS = gql`
 | 
			
		||||
  query GetTracks {
 | 
			
		||||
    tracksForHome {
 | 
			
		||||
      id
 | 
			
		||||
      title
 | 
			
		||||
      thumbnail
 | 
			
		||||
      length
 | 
			
		||||
      modulesCount
 | 
			
		||||
      author {
 | 
			
		||||
        name
 | 
			
		||||
        photo
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
`;
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
The convention is to name the query constant in `ALL_CAPS`.
 | 
			
		||||
 | 
			
		||||
### `useQuery` hook
 | 
			
		||||
 | 
			
		||||
The `useQuery` hook provides a straightforward wrapper for sending queries and receiving data back from the server.
 | 
			
		||||
 | 
			
		||||
When a component renders, `useQuery` returns an object from the Apollo Client that contains loading, error, and data properties.
 | 
			
		||||
 | 
			
		||||
```jsx
 | 
			
		||||
const { loading, error, data } = useQuery(TRACKS);
 | 
			
		||||
 | 
			
		||||
const Tracks = () => {
 | 
			
		||||
  const { loading, error, data } = useQuery(TRACKS);
 | 
			
		||||
 | 
			
		||||
  if (loading) return "Loading...";
 | 
			
		||||
 | 
			
		||||
  if (error) return `Error! ${error.message}`;
 | 
			
		||||
 | 
			
		||||
  return <Layout grid>{JSON.stringify(data)}</Layout>;
 | 
			
		||||
};
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
- We destructure the `loading, error, data` variables that are returned from the hook
 | 
			
		||||
- We pass in our query constant as an argument.
 | 
			
		||||
- In the example we just render the serialized data but we could of course pass the data as a prop and map through it in an embedded child component.
 | 
			
		||||
							
								
								
									
										113
									
								
								Databases/GraphQL/Apollo/Apollo_Server.md
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								Databases/GraphQL/Apollo/Apollo_Server.md
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,113 @@
 | 
			
		|||
---
 | 
			
		||||
title: Apollo Server
 | 
			
		||||
categories:
 | 
			
		||||
  - Databases
 | 
			
		||||
tags: [graph-ql, apollo]
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
# Apollo Server
 | 
			
		||||
 | 
			
		||||
> Apollo Server is the part of the Apollo suite that we use to create the backend of a GraphQL project; a GraphQL server.
 | 
			
		||||
 | 
			
		||||
It is able to do the following:
 | 
			
		||||
 | 
			
		||||
- Receive an incoming GraphQL query from a client
 | 
			
		||||
- Validate that query against the server schema
 | 
			
		||||
- Populate the queried schema fields
 | 
			
		||||
- Return the fields as a response
 | 
			
		||||
 | 
			
		||||
## Example schema
 | 
			
		||||
 | 
			
		||||
We will use the following schema in the examples
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
const typeDefs = gql`
 | 
			
		||||
  type Query {
 | 
			
		||||
    "Get tracks array for homepage grid"
 | 
			
		||||
    tracksForHome: [Track!]!
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  "A track is a group of Modules that teaches about a specific topic"
 | 
			
		||||
  type Track {
 | 
			
		||||
    id: ID!
 | 
			
		||||
    "The track's title"
 | 
			
		||||
    title: String!
 | 
			
		||||
    "The track's main author"
 | 
			
		||||
    author: Author!
 | 
			
		||||
    "The track's main illustration to display in track card or track page detail"
 | 
			
		||||
    thumbnail: String
 | 
			
		||||
    "The track's approximate length to complete, in minutes"
 | 
			
		||||
    length: Int
 | 
			
		||||
    "The number of modules this track contains"
 | 
			
		||||
    modulesCount: Int
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  "Author of a complete Track"
 | 
			
		||||
  type Author {
 | 
			
		||||
    id: ID!
 | 
			
		||||
    "Author's first and last name"
 | 
			
		||||
    name: String!
 | 
			
		||||
    "Author's profile picture url"
 | 
			
		||||
    photo: String
 | 
			
		||||
  }
 | 
			
		||||
`;
 | 
			
		||||
module.exports = typeDefs;
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Setting up the server
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
const { ApolloServer } = require("apollo-server");
 | 
			
		||||
const typeDefs = require("./schema");
 | 
			
		||||
const server = new ApolloServer({ typeDefs });
 | 
			
		||||
 | 
			
		||||
server.listen().then(() => {
 | 
			
		||||
  console.log(`
 | 
			
		||||
        Server is running!
 | 
			
		||||
        Listening on port 4000
 | 
			
		||||
        Query at http://localhost:4000
 | 
			
		||||
  `);
 | 
			
		||||
});
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
When we access the local URL we are able to access the Apollo server using the Explorer GUI. This automatically loads our schema and is basically a more fancy version of GraphiQL:
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
It makes it easy to read descriptions of the dataypes and to construct queries by clicking to insert fields.
 | 
			
		||||
 | 
			
		||||
### Adding some mock data
 | 
			
		||||
 | 
			
		||||
We are not connected to a database yet but we can create a mock that will enable us to run test queries.
 | 
			
		||||
 | 
			
		||||
We do this just by updating the Apollo Server options. We can either use generic dummy data or provide our own mock.
 | 
			
		||||
 | 
			
		||||
#### Generic mock
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
const server = new ApolloServer({ typeDefs, mocks: true });
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### Custom mock
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
const mocks = {
 | 
			
		||||
  Track: () => ({
 | 
			
		||||
    id: () => "track_01",
 | 
			
		||||
    title: () => "Astro Kitty, Space Explorer",
 | 
			
		||||
    author: () => {
 | 
			
		||||
      return {
 | 
			
		||||
        name: "Grumpy Cat",
 | 
			
		||||
        photo:
 | 
			
		||||
          "https://res.cloudinary.com/dety84pbu/image/upload/v1606816219/kitty-veyron-sm_mctf3c.jpg",
 | 
			
		||||
      };
 | 
			
		||||
    },
 | 
			
		||||
    thumbnail: () =>
 | 
			
		||||
      "https://res.cloudinary.com/dety84pbu/image/upload/v1598465568/nebula_cat_djkt9r.jpg",
 | 
			
		||||
    length: () => 1210,
 | 
			
		||||
    modulesCount: () => 6,
 | 
			
		||||
  }),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const server = new ApolloServer({ typeDefs, mocks });
 | 
			
		||||
```
 | 
			
		||||
| 
						 | 
				
			
			@ -7,7 +7,7 @@ tags: [graph-ql]
 | 
			
		|||
 | 
			
		||||
# Creating a GraphQL server
 | 
			
		||||
 | 
			
		||||
> We will use Node.js to create a basic GraphQL server that will serve data from a product database
 | 
			
		||||
> We will use Node.js to create a basic GraphQL server that will serve data from a product database.
 | 
			
		||||
 | 
			
		||||
Our server will allow us to add products to a database through a mutatation and to query the products that we have added. We will use a JS object instead of a real database.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -226,7 +226,11 @@ mutation {
 | 
			
		|||
      soldout: false
 | 
			
		||||
      stores: [{ store: "London" }]
 | 
			
		||||
    }
 | 
			
		||||
  )
 | 
			
		||||
  ) {
 | 
			
		||||
    price
 | 
			
		||||
    name
 | 
			
		||||
    soldout
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -234,12 +238,13 @@ This is represented in GraphiQL as follows:
 | 
			
		|||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
// TODO: Add bit about the value we want returned see 8:20 and explain what is returned
 | 
			
		||||
We should always return something, even if we are applying  mutation, hence we add the properties at the bottom as the ones we want to return.
 | 
			
		||||
 | 
			
		||||
### Returning a product through a query
 | 
			
		||||
 | 
			
		||||
```graphql
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
// Add new image of this working in GraphiQL
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,7 +8,9 @@ tags: [graph-ql]
 | 
			
		|||
 | 
			
		||||
SDL is the formal name for the syntax of GraphQL schemas.
 | 
			
		||||
 | 
			
		||||
A schema is a collection of object types that contain fields. Each field has a type of its own. A field's type can be a primitive/scalar value (such as an Int or a String), or it can be another object type (just like a custom type in TS).
 | 
			
		||||
## Types
 | 
			
		||||
 | 
			
		||||
A schema is a collection of object types that contain fields. Each field has a type of its own. A field's type can be a primitive/scalar value (such as an `Int` or a `String`), or it can be another object type (just like a custom type in TS).
 | 
			
		||||
 | 
			
		||||
A schema's type can be non-nullable which is to say, a required field. We indicate this with `!`.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -30,6 +32,39 @@ type Pet {
 | 
			
		|||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Queries
 | 
			
		||||
 | 
			
		||||
A query is also a schema type but of a special sort.
 | 
			
		||||
 | 
			
		||||
> The fields of this type are entry points into the rest of the schema. These are the top-level fields that the client can query for.
 | 
			
		||||
 | 
			
		||||
For example if we had this type:
 | 
			
		||||
 | 
			
		||||
```graphql
 | 
			
		||||
type Track {
 | 
			
		||||
  id: ID!
 | 
			
		||||
  title: String!
 | 
			
		||||
  author: Author!
 | 
			
		||||
  thumbnail: String
 | 
			
		||||
  length: Int
 | 
			
		||||
  modulesCount: Int
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
We could define a type to access a give `Track` as follows:
 | 
			
		||||
 | 
			
		||||
```graphql
 | 
			
		||||
type Query {
 | 
			
		||||
  tracksForHomePage: [Track!]!
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Then use this type as the basis for a query:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Descriptions
 | 
			
		||||
 | 
			
		||||
Descriptions are comments that allow you to document your Schema
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue