创建一个代码谱投稿应用程序#5(使用graphql-code-generator进行类型定义)

←上一篇文章

这次要做的事情

上次我們是從前端發送 GraphQL 查詢以顯示分數列表,但分數的類型是我們手動創建的。之前的程式碼如下:

...

type Score = {
  id: Number
  title: String
}

...

我們將使用graphql-code-generator來一鍵生成此命令的型別定義。

安装图书馆

首先需要安装库。

$ yarn add -D @graphql-codegen/cli

安装其他必要的插件

$ yarn add --dev @graphql-codegen/typescript @graphql-codegen/typescript-graphql-request @graphql-codegen/typescript-operations @graphql-codegen/typescript-react-apollo

安装

当您执行以下命令时,它将以交互方式帮您创建配置文件。(您也可以自行创建配置文件)

$ npx graphql-codegen init

因为会被问到各种问题,所以我会一一回答。
以下是我所回答的内容。

? Where is your schema?: (path or url) http://localhost:3000/graphql
? Where are your operations and fragments?: ./graphql/documents/**/*.graphql
? Pick plugins: TypeScript (required by other typescript plugins), TypeScript Operations (operations and fragments), TypeScript React Apollo (typed 
components and HOCs)
? Where to write the output: ./graphql/generated.tsx
? Do you want to generate an introspection file? No
? How to name the config file? codegen.yml
? What script in package.json should run the codegen? codegen

简单来说,需要解释一些重要的事情。

你的模式在哪里?

我正在编写服务器端的GraphQL端点。从该端点读取模式并对其进行类型定义等操作。

你的操作和片段在哪里?

我将创建一个用于编写在前端使用的查询(query)和变更(mutation)的文件(我将在接下来的工作中创建它)。这次我打算创建一个名为graphql的文件夹,并分别将查询放在/graphql/query/〇〇.graphql,将变更放在/graphql/mutation/〇〇.graphql中,所以我会这样做。

输出写在哪里?

当您输入命令时,这里将显示类型定义。

怎样给配置文件命名?
在 package.json 中应该运行哪个脚本来执行代码生成?

根据配置添加命令到 package.json。

这里是已经完成的设置文件。

overwrite: true
schema: "http://localhost:3000/graphql"
documents: "./graphql/documents/**/*.graphql"
generates:
  ./graphql/generated.tsx:
    plugins:
      - "typescript"
      - "typescript-operations"
      - "typescript-react-apollo"

package.json中添加了命令。

  ...
  "private": true,
  "scripts": {
    "dev": "next dev -p 3001",
    "build": "next build",
    "start": "next start",
+   "lint": "next lint",
+   "codegen": "graphql-codegen --config codegen.yml"
  },
  "dependencies": {
  ...

执行命令

以上是设定完成!在执行命令之前,我们将在前端编写要使用的查询。我们将编写一个查询来获取上次使用的Score列表。

query Scores {
  scores {
    id
    title
  }
}

用这个来执行命令。
yarn下面是刚刚在package.json中添加的命令。

$ yarn codegen

一切都没有问题,以下是创建的类型定义!

import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
export type Maybe<T> = T | null;
export type InputMaybe<T> = Maybe<T>;
export type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] };
export type MakeOptional<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]?: Maybe<T[SubKey]> };
export type MakeMaybe<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]: Maybe<T[SubKey]> };
const defaultOptions = {} as const;
/** All built-in and custom scalars, mapped to their actual values */
export type Scalars = {
  ID: string;
  String: string;
  Boolean: boolean;
  Int: number;
  Float: number;
  ISO8601DateTime: any;
};

export type Mutation = {
  __typename?: 'Mutation';
  /** An example field added by the generator */
  testField: Scalars['String'];
};

export type Query = {
  __typename?: 'Query';
  score: Score;
  scores: Array<Score>;
};


export type QueryScoreArgs = {
  id?: InputMaybe<Scalars['Int']>;
};

export type Score = {
  __typename?: 'Score';
  createdAt: Scalars['ISO8601DateTime'];
  id: Scalars['ID'];
  title?: Maybe<Scalars['String']>;
  updatedAt: Scalars['ISO8601DateTime'];
};

export type ScoresQueryVariables = Exact<{ [key: string]: never; }>;


export type ScoresQuery = { __typename?: 'Query', scores: Array<{ __typename?: 'Score', id: string, title?: string | null }> };


export const ScoresDocument = gql`
    query Scores {
  scores {
    id
    title
  }
}
    `;

/**
 * __useScoresQuery__
 *
 * To run a query within a React component, call `useScoresQuery` and pass it any options that fit your needs.
 * When your component renders, `useScoresQuery` returns an object from Apollo Client that contains loading, error, and data properties
 * you can use to render your UI.
 *
 * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
 *
 * @example
 * const { data, loading, error } = useScoresQuery({
 *   variables: {
 *   },
 * });
 */
export function useScoresQuery(baseOptions?: Apollo.QueryHookOptions<ScoresQuery, ScoresQueryVariables>) {
        const options = {...defaultOptions, ...baseOptions}
        return Apollo.useQuery<ScoresQuery, ScoresQueryVariables>(ScoresDocument, options);
      }
export function useScoresLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<ScoresQuery, ScoresQueryVariables>) {
          const options = {...defaultOptions, ...baseOptions}
          return Apollo.useLazyQuery<ScoresQuery, ScoresQueryVariables>(ScoresDocument, options);
        }
export type ScoresQueryHookResult = ReturnType<typeof useScoresQuery>;
export type ScoresLazyQueryHookResult = ReturnType<typeof useScoresLazyQuery>;
export type ScoresQueryResult = Apollo.QueryResult<ScoresQuery, ScoresQueryVariables>;

使用所创建的类型定义进行重写

使用实际生成的类型定义,我将上次创建的index.tsx进行了改写,以下是改写后的代码。

import { Box } from '@chakra-ui/react'
import type { ReactElement } from 'react'
import { Layout } from '../components/common/Layout'
import type { NextPageWithLayout } from './_app'
import { useQuery } from "@apollo/client";
import { Score, ScoresDocument } from '../graphql/generated';

const Page: NextPageWithLayout = () => {
  const { data, loading, error } = useQuery(ScoresDocument)
  if (loading) return <Box>ロード中...</Box>;
  if (error) return <Box>{error.message}</Box>;
  return (
    <Box>
      <ul>
        {data.scores.map((score: Score) => (
          <li>{score.title}</li>
        ))}
      </ul>
    </Box>
  )
}

Page.getLayout = function getLayout(page: ReactElement) {
  return (
    <Layout>
      {page}
    </Layout>
  )
}

export default Page

查询也可以被重写为ScoresDocument的形式,并且之前自己创建的Score类型定义也是使用服务器端的schema生成的,因此类型安全性得到了提高!

這次就到這裡吧!

只需要一种选择的原文重述:

我参考了一下那个网站或文章。

GraphQL 代码生成器
初次接触 GraphQL。使用代码生成器来生成类型的笔记。

广告
将在 10 秒后关闭
bannerAds