关于react-native:React-Native填坑之旅GraphQL

37次阅读

共计 5845 个字符,预计需要花费 15 分钟才能阅读完成。

GraphQL 还是通过 Http 的 GET 和 POST 的形式返回数据,只是 GET 的长度限度导致可能的查问会出问题。所以个别都能够用 POST 来获取、批改数据。这就是说 GraphQL 在客户端 App 来说能够和平时申请 API 的形式齐全一样。在根本应用上,有没有第三方 graphql client 的库的帮忙都没什么区别。

GraphQL 是啥

在正式开始之前,略微介绍一下 GraphQL。如果你的我的项目稍有规模,那么你肯定禁受过一种折磨。一个很久之前的 API 返回了巨多务必的数据,是能够齐全服务当初的需要。然而显著数据过多在要求性能的时候,在后端数据是查出来的,有缓存也得拜访了缓存能力返回并不是没有代价。在前端占了带宽返回就慢。而后从一大堆数据里拿出你想要的也要代价。前面的保护对于前后端都是可能产生辣手的问题。之所以 FB 要提出 GraphQL 的规范也是因为 FB 自身反对的产品太多遇到了这样的问题。

如果客户端这边说有了什么需要,就获取这个需要的必要数据,那么根本就要新开发 API。GraphQL 就是一个你要啥就返回啥的微小 API。能够查问你指定的数据,也能够批改后端的数据。查问就是Query,批改操作叫做Mutation

查问:

query {
    todos {
      id
      title
    }
  }

这是一个查问。要查问的是 todos(能够临时了解为一个表),要查问的是 idtitle两个字段。这个查问只会返回 idtitle两个字段对应的数据。

也能够是带条件的查问:

  query ($from: Int!, $limit: Int!) {todos (from: $from, limit: $limit) {
      id
      title
    }
  }

新增、批改

mutation CreateReviewForEpisode($ep: Episode!, $review: ReviewInput!) {createReview(episode: $ep, review: $review) {
    stars
    commentary
  }
}

返回

{
  "data": {
    "createReview": {
      "stars": 5,
      "commentary": "This is a great movie!"
    }
  }
}

根本介绍就到这里。具体能够参考官网文档。

为啥不是 Relay

官网的库专职负责劝退有没有领会过。GraphQL 是 Facebook 提出来的一个规范,留神这是一个规范而不是实现。服务端的状况不熟不多做介绍,然而在客户端 FB 或者当初叫 Meta 了,给出了一个实现并且曾经倒退了很多年。这个库叫做 Relay。

它凭借弱小的性能和 Meta(当年 FB)背书,很快倒退了起来。不过这个工具显然曾经有点后劲不足了。从当初 TypeScript 我的项目倒退的状况来看,它显然不足对 TypeScript 的反对。比方它的一个配套 babel 插件没有对 TypeScript 的反对。当然也是一个小问题,只须要在本人的我的项目里增加一个 index.d.ts 文件并增加类型就能够。

而后是它的模式。在你依照官网文档的 Step by step 一步一步走完的话,你还是不能做开发。因为你在增加另外一个文件的和查问的时候就会发现,这个须要的查问并不会主动生成。要么是悄没声的没有报错也没有生成对应的文件,要么是报一些莫名其妙的错。因为你须要依据你的文件名来命名查问(或者任何的操作)。也就是它的模式能够认为是强侵入的,尽管会比其余的形式少写一些固定代码,尽管也不肯定。笔者程度无限,只好先弃了。

URQL 怎么样

首先,urql 在 github 有 6.5K 的 star。并且设计也足够沉闷。最初被后还有个公司反对。不能说不是 KPI 我的项目,然而 KPI 我的项目也有个益处,至多有为了 KPI 的人在保护代码。

另外,这个库是用 TypeScript 开发的。也就是说它必定是 TypeScript 敌对的,你的我的项目如果用了 TypeScript,在类型上不必放心过期、不残缺等问题。

并不是其余的库不适合,更多能够抉择的库在 GraphQL 官网里有列出来。

用一下现成的 GraphQL 服务:Github

Github 很久以前就提供了 GraphQL API。咱们就在 APP 里调用 github 的 GraphQL API。用来查问某个 owner(比方 facebook)上面的公开代码库。

要应用 github 的 GraphQL 服务须要用到 token,所以须要一个输出 token 的界面。在用户输出 token 后能够长久化存储这个 token。还须要有一个界面能够删掉这个 token,让用户有机会能够输出新的 token。尤其用户批改了权限之后,那么就必须要有一个更新 token 的中央。

导航

用户在进入 APP 之后,在点击 Repo 选项之后,! 如果不存在这么一个 Token,则会进入 token 页面。在用户输出 token 之后能力持续前面的性能。

用户在输出 Token 页输出 token 后跳转到列表页。在 Settings 页能够删掉 Token,而后主动跳转到 Token 页。

在用户胜利输出 token,进入 repo 列表页能够看到 repo 列表。当初只显示 facebook 上面的公开 repo。前面退出 search bar 能够输出 owner,这样就能够管制要搜寻的是哪些 repo 了。

URQL 根本配置

urql 的配置分两局部。第一是 provider 的配置。应用 provider 能够让所有调用 graphql api 的中央都很不便的拿到申请的 endpoint 和须要的 auth token。当然不是明文的读取而是能够间接调用查问。

配置 Provider

App.tsx 能够看到:

    <Provider value={client}>
      <NavigationContainer>
        <Stack.Navigator initialRouteName="Token">
          <Stack.Screen
            name="Tabs"
            component={Tabs}
            options={{headerShown: false}}
          />
        </Stack.Navigator>
      </NavigationContainer>
    </Provider>

这个 Provider 和 react-redux 的 provider 的作用一样。这里 urql 的 provider 提供的是一个 client。

Exchange

Exchange是 urql 的一个中间件机制。这个机制也和 Redux 的中间件机制相似。

这里咱们须要给官网提供的 authExchange 填空,把获取和应用 token 的逻辑加进去。

首先须要装置authExchange

yarn add @urql/exchange-auth

而后在门路:src/data/graphqlClient.ts下能够看到给 authExchange 填空的代码。在这里须要增加的除了上文说的获取 token,应用 token 之外还有错误处理的内容。之类为了简略,错误处理的局部先疏忽。有须要的同学能够钻研官网实例。

获取 token 的办法是getAuth。咱们的 token 是在 Github 配置生成,而后用户残缺增加并存储在 APP 的里。所以不须要额定的 API 调用获取 token。

  getAuth: async ({authState}): Promise<AuthState | null> => {
    try {if (!authState) {const token = await AsyncStorage.getItem(GITHUB_TOKEN_KEY);
        return {token} as AuthState; // *
      }
      return null;
    } catch (e) {return null;}
  },

在加星这一步能够看到,token 是作为 authState 对象的一个属性返回了。

应用 token 是通过办法 addAuthToOperation 实现的。在这里最初会返回一个新建的 operation。外面就寄存了从 getAuth 拿到的 token:

  addAuthToOperation: ({authState, operation}) => {
    // ... 略
    return makeOperation(operation.kind, operation, {
      ...operation.context,
      fetchOptions: {
        ...fetchOptions,
        headers: {
          ...fetchOptions.headers,
          Authorization: `Bearer ${authState.token}`,  // *
        },
      },
    });
  },

在加 * 这一步应用了 token,从 authState 里读出了 token 放在 header 的认证里随着 api 申请发送到了后端。

填充 urql 的 client

通过 Exchange 配置好了 token 之后,要害的一步就实现了。接下来就须要把配置号的 exchange 和 graphql 的 endpoint 都增加到 client 里供 graphql 的查问应用。

const getGraphqlClient = () => {
  const client = createClient({
    url: 'https://api.github.com/graphql', // 1
    exchanges: [
      dedupExchange,
      cacheExchange,
      authExchange({    // 2
        ...authConfig,
      }),
      fetchExchange,
    ],
  });

  return client;
};

export {getGraphqlClient}; // 3
  1. 在 url 属性增加 github 的 graphql 的 endpoint:https://api.github.com/graphql
  2. 把 auth exchange 增加到 exchange 数组里。在这里配置的时候须要留神同步操作的 exchange 要放在异步操作的 exchange 后面。所以,authExchange要放在第三位。

实现一个查问

实现了下面的配置之后,咱们能够开始实现一个简略的查问了。

src/GithubScreen.tsx 文件里能够看到具体的查问和执行后的成果。

首先来筹备咱们的查问语句。

import {gql, useQuery} from 'urql'; // 1

const REPO_QUERY = gql`    // 2
  query searchRepos($query: String!) {search(query: $query, type: REPOSITORY, first: 50) {
      repositoryCount
      pageInfo {
        endCursor
        startCursor
      }
      edges {
        node {
          ... on Repository {name}
        }
      }
    }
  }
`;
  1. 引入 urql 到工具办法 gql 和 useQuery。useQuery 前面会用到
  2. 编写查问语句。

这个查问语句看起来会让初学者手足无措。下面的例子咱们也只是提到了 query,metation 之类少数几个关键字。那么这么长的(还不算长)查问语句如何能写进去呢。github 专门提供了一个 graphql api 的 explorer。点击这里到 explorer。事实上,在很多语言对 GraphQL 的实现里都有这样一个 explorer,至多是在开发阶段能够享受到这个服务。

  • 首先在这个页面登录你的 github 账号。
  • 在 GraphiQL 里就能够测试各种各样的查问语句了。
  • 如果你有 schema 不分明的能够看最右面的 Doc 文档
  • 左下角的 Query Variable 能够输出查问的变量。这里就是 query,对应的是 repo 的 owner 和 repo 的 license 类型。
  • 两头一列就是查问的后果。

在两头看到查问后果之后,就能够判断你的查问语句是否适合。在本例中就是咱们须要的查问语句了,间接复制到咱们的代码里应用。

或者,如果你对于 schema 的定义略有理解的话,比方咱们这次要查问的是 repository。也能够应用查问语句编辑器外面的智能提醒。整个来说,编写查问、批改语句是十分不便的。

一个简略的查问

下面说到如何编写一个查问语句,当初来应用这个语句查问 repo 列表。

urql 也提供了这样的一个 hook 给 react 应用。

import {gql, useQuery} from 'urql';  // 1

const REPO_QUERY = gql `query searchRepos(...) {...}`;

const GithubScreen = () => {const [result] = useQuery({  // 2
    query: REPO_QUERY,
    variables: {query: 'user:facebook'},
  });

  const {data, fetching, error} = result; // 3

  // ... 略...

}

很简略一个简略的查问就能够搞定了。

  1. 只须要请 useQuery 出场。
  2. 应用 useQuery。这个 hook 还会返回一个从新执行查问的办法,次要使给刷新时应用。
  3. 网络申请三状态,data 是数据,fetching 示意申请中,error 是查问呈现谬误。

前面的代码能够依据呈现的作出不同解决。

最初在 FlatList 中显示 user 是 facebook 的所有公开 repo。

最初

一个简略的查问在这个 app 里就曾经实现了。然而显然还有一些工作须要做。比方,loading 和 error 解决都显得比拟简陋。咱们在后面的系列里提到了 redux-toolkit。是否能够有一个 slice 来让这些逻辑的解决和 redux 联合在一起。

咱们在依赖里也曾经增加了 react-native-paper 组件库。这个库能够在 native 和 web 上通用。我还没有把 web 断的截图放上来,次要因为有点惨不忍赌。UI 也能够在前面稍作丑化。

最次要的工作是如何在理论的开发中应用 graphql。它的后劲绝不只是看起来很新鲜这么简略看,而是能够实实在在的解决问题的。前端的同学会遇到一个最大的阻力就是来自于后端同学是否接管这一不太新的新事物。

在 youtube 上有一个 30 分钟搞定 graphql 的视屏,点这里能够看。理论后端要整合 graphql 必定不会像视屏里的那么容易,而且他自身也仅仅演示了查问操作的解决。不过也不会像设想的那么难。GraphQL 是一个规范,在实现上也是由从内部查问语句到外部获取数据之间的转换,也就是视频里的resolver,和 schema 定义。它仍然依赖于底层的“DAO”层,或者是 rest api 的 http 申请。在 GraphQL 实现之后的收益就十分的不言而喻,数据生产端(各种 App)对于后端批改的需要会大幅度缩小。摆弄 query 语句就能够何必后端新增 API 呢?

正文完
 0