Skip to content

stepzen-dev/workshop-graphql-frontend

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

GraphQL For Frontend Developers Workshop

There are many advantages to using GraphQL as a datasource for frontend development, compared to REST APIs. We developers in example need to write a lot of imperative code to retrieve data to display in our applications and handle state. With GraphQL you cannot only decrease the amount of code needed around data fetching and state-management you'll also get increased flexibility, better performance and most of all an improved developer experience. In this workshop you'll learn how to handle GraphQL in your frontend React application, compare different clients and can even auto generate code based on GraphQL!

Getting Started

Clone this repository (or fork it) and install all dependencies by running:

npm i
# or
yarn

After the installation is completed, run the development server:

npm run dev
# or
yarn dev

Open http://localhost:3000 with your browser to see the result. Mocked data from and DEV.to is being pulled into the application using GraphQL and StepZen.

You can start editing the page by modifying pages/index.js. The page auto-updates as you edit the file.

Exercises

Excercise 1

This application uses a mocked GraphQL API for Github and DEV.to, you can explore it in StepZen GraphQL Studio or using GraphiQL. From StepZen GraphQL Studio, you can find the GraphQL API endpoint that leads to GraphiQL in the top-right of your screen (or here).

Run the following query that will combine information from a (mocked) Github user and its repositories and articles from DEV.to:

{
  github_user(login: "githubteacher") {
    bio
    repositories {
      edges {
        node {
          id
          name
        }
      }
    }
  }
  devto_getArticles(username: "cerchie") {
    title
    url
  }
}

Can you alter the query to get the description, stargazerCount (number of stars), and the updatedAt fields from Github? This query needs to be added to the function that fetches the data from the GraphQL API in pages.index.js.

Show solution

The new query becomes:

{
  github_user(login: "githubteacher") {
    bio
    repositories(first: 5) {
      edges {
        node {
          id
          name
          description
          stargazerCount
          updatedAt
        }
      }
    }
  }
  devto_getArticles(username: "cerchie") {
    title
    url
  }
}

Look at the code

This must be added to the fetch function on line 81. Save your code and return to the application on http://localhost:3000 to see more information being displayed for the (mocked) repositories.

Excercise 2

The query you've used in the previous exercise has a query parameter, which can be better handled from a named query. Next to helping you to handle query variables, named queries are important for your GraphQL API and Client later, as they are often used for caching purposes.

Go to StepZen GraphQL Studio or GraphiQL and change the query to a named one that takes the login query parameter. Also, use this named query in the fetch function in pages/index.js. How would you handle the variable for the query parameter?

Hint: It doesn't matter how you name your query.

Show solution

The named query must be added to the fetch function around line 81. The query and the variable for the query parameter are added as follows:

Look at the code

Excercise 3

So far we've been using mocked data to get the Github and DEV.to information, but let's use some real data. More importantly, your own Github data (and DEV.to if you have an account)! From StepZen GraphQL Studio you can select to use mocked data, or actual data for which you need to have a Github Personal Access Token. Create a Github personal access token here.

After creating a Github Personal Access Token go to StepZen GraphQL Studio and deselect the "mocked" toggle. The GraphQL schema for this endpoint will change and a new endpoint will be generated. You can find the new endpoint in the top-right of the screen (or here).

Try getting your own Github repositories by adding your Personal Access Token for the github_token query parameter in GraphiQL, and replace the GraphQL API endpoint and query in pages/index.js with new ones.

Show solution

The GraphQL API endpoint needs to be replaced with the new one, which has a different GraphQL schema that is requesting the data from the actual Github API. Also, it takes a value for github_token to get your data from Github. (Note: no 'Bearer' prefix required)

Look at the code

Excercise 4

Let's start using a JavaScript / GraphQL fetching library to get our data now, which you need to install from npm:

npm i graphql graphql-request
# or
yarn add graphql graphql-request

After installing these, you can replace the fetch method with the request method. This should look something like this:

import { request, gql } from 'graphql-request';

const query = gql`
  {
    Movie(title: "Inception") {
      releaseDate
      actors {
        name
      }
    }
  }
`;

const result = await request('YOUR_GRAPHQL_ENDPOINT', query, {
  /* variables */
}).then((data) => (data));

You may need to adjust how props are returned since there will be no data wrapper:

  return {
    props: {
      ...result
    },
  };

Replace the GraphQL API endpoint, query and variables with the correct values!

Show solution

Look at the code

Excercise 5

Suppose you want to do multiple queries from your application, like to get a specific repository when you click a link. You don't want to duplicate the configuration for your GraphQL request in every method. Instead, you can create a client instance that can be used for every query you want to run. Create a new file pages.client.js in which you define this instance https://github.com/prisma-labs/graphql-request#usage.

Refactor the request method in pages/index.js to use the client instance. Also, open the file repository/[...params].js. Import the client and use a request method to get the data for this page. The page should display a specific repository based on the params in the URL, e.g. http:localhost:3000/repository/stepzen-dev/examples should show the repository from (https://github.com/stepzen-dev/examples)[https://github.com/stepzen-dev/examples].

Hint: The a element to visit a repository detail page should look like <a key={id} href={repository/${owner.login}/${name}} className={styles.card}>. Where would you get this information from?

Show solution

In client.js you should have the following. Include an Authentication header with your StepZen API Key if you're not using the StepZen GraphQL Studio endpoint, but have deployed the schema on your own account.

In pages/index.js you need to import client from the file client.js, and use the request method from this client instance to query the GraphQL API.

Also, change the query so it will get the owner field.

Finally, in repository/[...params].js you should import the client instance so the repository data will be requested from the GraphQL API.

Look at the code

Excercise 5 - BONUS

When you're reusing fields in GraphQL queries, you can make use of a Fragment. The queries used in pages/index.js and pages/repository/[...param].js both need fields from a Github repository. How would you write this fragment?

Show solution

const query = gql`
  fragment RepositoryFields on Github_Repository {
    id
    name
    description
    stargazerCount
    updatedAt
  }

  query GetGithubRepository(
    $name: String!
    $owner: String!
    $github_token: Secret!
  ) {
    github_repository(name: $name, owner: $owner, github_token: $github_token) {
      ...RepositoryFields
    }
  }
`;

Excercise 6

Our GraphQL API supports cursor-based pagination, which we can make use of in the application. If you'd look at the following query:

query MyQuery(
  $login: String!
  $username: String!
  $github_token: Secret!
  $first: Int!
  $after: String!
) {
  github_user(login: $login, github_token: $github_token) {
    bio
    repositories(first: $first, after: $after) {
      pageInfo {
        endCursor
        hasNextPage
      }
      edges {
        node {
          id
          name
          description
          stargazerCount
          updatedAt
        }
      }
    }
  }
  devto_getArticles(username: $username) {
    title
    url
  }
}

The query parameters for first and after are used for pagination. With first you define the amount of results, while after is the cursor of the last result on the previous page. Think of cursor as offset, which you might know from other pagination methods. To dynamically get the value for after you should use the value from the endCursor field in pageInfo. Also, hasNextPage lets you know if there is a next page based on first and endCursor values.

Implement pagination for the repositories in pages/index.js. Use a small value for first if you don't have many repositories linked to your Github account.

Show solution

Look at the code

Excercise 7

Let's convert our files to TypeScript, so we can autogenerate the code to do our requests to the GraphQL API. First, install GraphQL Codegen and it's dependencies:

npm i @graphql-codegen/cli @graphql-codegen/typescript @graphql-codegen/typescript-operations @graphql-codegen/typescript-graphql-request
# or
yarn add @graphql-codegen/cli @graphql-codegen/typescript @graphql-codegen/typescript-operations @graphql-codegen/typescript-graphql-request

Second, rename pages/index.js to pages/index.tsx. And install the following dependencies:

npm i --save-dev typescript @types/react@17 
# or 
yarn add --dev typescript @types/react@17 

Create a new file called codegen.yml with the following contents:

overwrite: true
schema: 'https://graphql07.stepzen.net/api/0777b07452dfe5d76ce46a4fecb3918d/__graphql'
documents: '**/*.graphql'
generates:
  graphql.ts:
    plugins:
      - 'typescript'
      - 'typescript-operations'
      - 'typescript-graphql-request'

Then create a file called queries.graphql and add all the queries from pages/index.js and pages/repository/[...param].js into it.

Finally, add the generate script to your package.json file:

  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint",
    "generate": "graphql-codegen --config codegen.yml"
  }

You can run npm run generate or yarn generate and a new file called graphql.ts is generated. This has types for your GraphQL schema from the URL from StepZen GraphQL Studio (or your own GraphQL API endpoint) and for the queries as defined in queries.graphql. Use the generated code for GraphQL Request in the application!

Show solution

Look at the code

Excercise 8 - BONUS

You can use React Query to add caching, prefetching, refetching, and tons of other features to your GraphQL application. See here for more information on React Query for GraphQL, as we're doing Server-side requests in this application make sure to follow these docs while setting up.

Show solution

Install react-query from npm:

npm i react-query
# or
yarn add react-query

And make the following changes:

Look at the code

Learn More

To learn more about Next.js, take a look at the following resources:

You can check out the StepZen GitHub repository - your feedback and contributions are welcome!

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published