本文介绍如何在 React 项目中使用 GraphQL 查询,同时配合 @graphql-codegen/cliopen in new window 代码自动生成工具提高开发效率。

初始化项目

初始化和安装依赖

我们使用 create-react-appopen in new window 来初始化前端项目,使用官方的 typescriptopen in new window 模板。

假设我们的项目名称是 bff-graphql-clientopen in new window

yarn create react-app bff-graphql-client --template typescript
1

等待几分钟后,项目初始化完成。

现在我们安装 GraphQL 的包。

yarn add graphql
1

由于 graphqlopen in new window 这个包使用起来非常繁琐,我们通过 @graphql-codegen/cli 来自动生成这些类型代码,我们只需要编写查询的 Query 即可。

yarn add -D @graphql-codegen/cli
1

我们使用 Apollo 客户端来实现查询,同时添加一些 typescript 插件来生成 typescript 代码。

yarn add -D @graphql-codegen/typescript @graphql-codegen/typescript-operations @graphql-codegen/typescript-react-apollo

yarn add @apollo/client
1
2
3

配置文件

安装完依赖包以后,我们通过 GraphQL Code Generator 的指引来生成配置文件,GraphQL Code Generator 会根据这个配置文件来生成代码。

yarn graphql-codegen init
1

根据命令行提示,我们生成配置文件。

codegen config

在生成的配置如下:

overwrite: true
schema: "http://localhost:3000/graphql" # graphql 服务的地址
documents: "src/**/*.graphql" # 查找项目中所有已 .graphql 结尾的文件,来生成代码
generates:
  src/generated/graphql.tsx: # 代码输出地址
    plugins:
      - "typescript"
      - "typescript-operations"
      - "typescript-react-apollo"
  ./graphql.schema.json:
    plugins:
      - "introspection"
1
2
3
4
5
6
7
8
9
10
11
12

因为我们要使用 Apollo 的客户端,同时使用 React Hook,因此需要对配置做一些修改:

overwrite: true
schema: "http://localhost:3000/graphql"
documents: "src/**/*.graphql"
generates:
  src/generated/graphql.tsx:
    plugins:
      - "typescript"
      - "typescript-operations"
      - "typescript-react-apollo"
    config:
      noComponents: true
      noNamespaces: true
      skipTypename: true
      withHooks: true # 使用 React Hook
      withComponent: false
      withHOC: false
      apolloReactHooksImportFrom: "@apollo/client" # 使用 Apollo Client
      apolloReactCommonImportFrom: "@apollo/client"
  ./graphql.schema.json:
    plugins:
      - "introspection"

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

相关配置的功能说明可以在这里open in new window找到,就不一一赘述了,这里只标出来比较关键的两个配置。

第一个查询

完成配置以后,我们现在来尝试查一下在上一篇文章中定义的商品信息。

自动化生成查询代码

先启动 GraphQL 服务,打开 playground 看看系统内有哪些模型可查。在上一篇文章中,我们定义了商品模型、订单模型。我们先来查一下商品模型。

我们先在 src 目录下新建一个 graphql 目录,用来存在所有的 .graphql 文件。

query Goods($param: GoodsParam!) {
  goodsData(param: $param) {
    goodsId
    goodsName
  }
}
1
2
3
4
5
6

将上面的内容保存在 src/graphql/goods.graphl 中。运行 yarn codegen,我们看到命令行显示运行成功,查看 src/generated/graphql.tsx 中生成了很多代码。

codegen output

我们在生成的代码中看到了这两个函数,我们会用他们来查询商品信息:

export function useGoodsQuery(baseOptions: ApolloReactHooks.QueryHookOptions<GoodsQuery, GoodsQueryVariables>) {
        const options = {...defaultOptions, ...baseOptions}
        return ApolloReactHooks.useQuery<GoodsQuery, GoodsQueryVariables>(GoodsDocument, options);
      }
export function useGoodsLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions<GoodsQuery, GoodsQueryVariables>) {
          const options = {...defaultOptions, ...baseOptions}
          return ApolloReactHooks.useLazyQuery<GoodsQuery, GoodsQueryVariables>(GoodsDocument, options);
        }
1
2
3
4
5
6
7
8

useGoodsQuery 是立即查询,useGoodsLazyQuery 会返回一个函数,调用这个函数才会触发查询。详细信息可以查看这两函数的签名。

每次修改 .graphql 文件都执行一次 yarn codegen 是非常麻烦的。我们来开启 @graphql-codegen/cliwatch 模式,来实现自动化生成。

{
    "scripts": {
        "codegen": "graphql-codegen --config codegen.yml --watch"
    },
}
1
2
3
4
5

此时再执行 yarn codegen,控制台显示:

codegen watch

使用 ApolloClient

先在 src/index.tsx 中完成 ApolloClient 的初始化和配置。

import { ApolloClient, ApolloProvider, HttpLink, InMemoryCache } from "@apollo/client";

const apolloClient = new ApolloClient({
  link: new HttpLink({
    uri: "http://localhost:3000/graphql",
  }),
  cache: new InMemoryCache(),
  defaultOptions: {
    query: {
      errorPolicy: "all",
      fetchPolicy: "network-only",
    },
    watchQuery: {
      errorPolicy: "all",
      fetchPolicy: "network-only",
    },
  },
});

ReactDOM.render(
  <React.StrictMode>
    <ApolloProvider client={apolloClient}>
      <App />
    </ApolloProvider>
  </React.StrictMode>,
  document.getElementById("root")
);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

配置完成后,稍微改造下 App.tsx,使用 useGoodsQuery 查询数据,并将数据展示出来:

import React from "react";
import { useGoodsQuery } from "./generated/graphql";

function App() {
  const { data, loading } = useGoodsQuery({
    variables: {
      param: {
        goodsId: "g-00001",
      },
    },
  });
  if (loading) {
    return <div className="App">loading data...</div>;
  }
  return <div className="App">{JSON.stringify(data?.goodsData, null, 4)}</div>;
}

export default App;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

此时运行 yarn start,我们可以在浏览器中看到输出的商品信息。

我们可以看到页面先显示 loading data... 然后显示查到的商品信息:

{ "__typename": "GoodsData", "goodsId": "g-0001", "goodsName": "商品名称" }
1

至此,我们就实现了在 React 项目中使用 GraphQL 查询数据。

总结

本文介绍如何在 React 项目中使用 GraphQL 查询数据。

通过 @graphql-codegen/cli 自动化生成代码,提高开发效率。文中展示了如何编写配置文件来启用 React Hook。

通过 --watch 参数来开启 @graphql-codegen/cli 的监听模式,实现 .graphql 变动自动化生成代码。

同时,我们使用 Apollo Client 来实现 GraphQL 查询,并展示了如何配置 Apollo Client。

关注微信公众号,获取最新推送~