Skip to content

Latest commit

 

History

History
320 lines (235 loc) · 5.5 KB

Lesson-9.md

File metadata and controls

320 lines (235 loc) · 5.5 KB

Subscriptions Lab

Learning Objectives

  • Write resolvers with parent
  • Describe resolvers in terms of schema
  • Use parent in resolvers
  • Organizing your work

Final Project Standup

In Groups conduct a standup focussing on the final project progress. Answer these questions:

  • What did you work on since Tuesday?
  • What Are you working on today?
  • What problems did you encounter?
  • Do you have any blockers?

GraphQL Slack Solution

This the solution I came up with the Slack-like graphql challenges.

This is not a definitive solution. You may have your own ideas that's okay!

Types:

  • Post
  • Channel
  • Query
  • Mutation
  • Subscription

Post Type:

type Post {
  message: String!
  date: String!
}

Channel Type:

type Channel {
	name: String!
	posts: [Post!]!
}

Query Type:

type Query {
  posts(channel: String!): [Post!]
  channels: [Channel!]!
}

Q: why not posts(channel: String!): [Post!]!?

Mutation type:

type Mutation {
  addPost(channel: String!, message: String!): Post
  addChannel(name: String!): Channel
}

Q: Why not return Post! or Channel!?

Subscription type:

type Subscription {
  newPost(channel: String!): Post
  newChannel: Channel!
}

Data Structure:

// Data Store
const data = {
  Main: [ { message: 'hello world', date: new Date() } ],
  Cats: [ { message: 'Meow', date: new Date() }],
  ...
}

GraphQL Resolvers and Apollo

The resolver should match the structure your schema describes.

At the top level

const resolvers = {
	Post: { },
	Channel: { },
	Query: { },
	Mutation: { },
	Subscription: {	}
}

Wait? It looks like we included Post and Channel?

Yep! You can resolver a for every type. If you don't define a resolver Apollo Server will define a default resolver for it!

We can look at the schema to determine the shape of each resolver.

Query Type:

type Query {
  posts(channel: String!): [Post!]
  channels: [Channel!]!
}
const resolvers = {
  ...
  Query: {
    posts: (_, { channel }) => { ... },
    channel: () => { ... }
  },
  ...
}

Mutation Type

type Mutation {
  addPost(channel: String!, message: String!): Post
  addChannel(name: String!): Channel
}
const resolvers = {
  ...
  Mutation: {
    addPost: (_, { channel, message }) => { ... },
    addChannel: (_, { name }) => { ... }
  },
  ...
}

Subscription Type

type Subscription {
  newPost(channel: String!): Post
  newChannel: Channel!
}
const resolvers = {
  ...
  Subscription: {
    newPost: {
      subscribe: (_, { channel }) => { ... }
    },
    newChannel: {
      subscribe: () => { ... }
    }
  },
  ...
}

What about the base types? Post and Channel?

These Are not required, if they are returned from on eo fthe other types or if they return a primitive type like: String, Int, etc.

If you do need them they can declare a resolver for field!

Channel Type

type Channel {
  name: String!
  posts: [Post!]!
}
const resolvers = {
  ...
  Channel: {
    name: (parent) => {
      return parent.name
    }
    posts: (parent) => {
      return parent.posts
    }
  },
  ...
}

Post Type

type Post {
  message: String!
  date: String!
}
const resolvers = {
  ...
  Post: {
    message: (parent) => {
      return parent.message
    }
    date: (parent) => {
      return new Date(parent.date).toLocaleDateString()
    }
  },
  ...
}

What is happening there?

The parent arguement provides the value from the previous/parent resolver.

Think of the resolver like a tree where values are passed from trunk to branch to leaf.

Challenges

  • Complete the Slack-Like server (see the challenges from lesson 8)
  • Define some resolvers for your types and their fields
    • Use the Parent argument!
  • Use class time to finish up the any unfinished work
    • Previous assignments
    • Final project (Check the schedule below)

After Class

You should decide an what you are going to do for the final project