• 日常搜索
  • 百度一下
  • Google
  • 在线工具
  • 搜转载

使用GraphQL、React Native和AWS AppSync编写应用程序:应用程序

您将要创建的内容

使用GraphQL、React Native和AWS AppSync编写应用程序:应用程序  第1张


在这些教程中,我将向您展示如何使用aws AppSync 和 react Native 创建 graphql 数据库并与之交互。这个应用程序将具有实时和离线功能,这是我们通过 AppSync 开箱即用的功能。 

在这篇文章中,我们将通过构建 React Native 客户端来完成这一切。该项目有点过于复杂,无法逐步引导您,但我将解释项目架构并向您展示源代码的关键部分。

应用架构和文件夹结构概述

我们的应用程序将有一个主入口点,该入口点将由两个选项卡式视图组成。一个选项卡将列出我们 GraphQL 数据库中的城市,另一个选项卡将是添加新城市的输入表单。Cities选项卡将是一个导航器,允许用户导航到各个城市。

我们将主要组件存储在文件夹中,并在src目录中拥有其他文件夹来保存我们的 GraphQL 突变、查询和订阅。

我们还将有一个资产文件夹来保存我们的图像。

使用GraphQL、React Native和AWS AppSync编写应用程序:应用程序  第2张

创建和配置 React Native 客户端

作为参考,请查看 教程 GitHub 存储库中此应用程序的最终代码,但我将概述我从头开始创建应用程序所采取的一些步骤。

首先,我们使用Expo创建了一个新的 React Native 应用程序 。 

在新创建的项目中,我们安装了我们的依赖项。对于 GraphQL 和 AppSync 功能,我们使用了以下依赖项:

aws-appsync
aws-appsync-react
graphql-tag
react-apollo
uuid

我们还在 UI 设计中使用了以下依赖项:

react-navigation
react-native-elements
react-native-vector-icons

此外,一旦安装了 Vector Icons 库,我们将其链接:

react-native link react-native vector-icons

安装依赖项后,我们从 AppSync 控制台下载了 AppSync.js 文件。在我们的 AppSync 项目控制台中,我们在底部选择了 React Native  ,然后单击橙色的下载按钮下载此配置文件。

使用GraphQL、React Native和AWS AppSync编写应用程序:应用程序  第3张

此配置文件包含我们创建新客户端所需的 AppSync 客户端信息。 

配置提供者和存储

应用程序的顶层是我们将在其中进行配置以将 AppSync api与 React Native 客户端连接起来。 如果你之前使用过redux或 React Apollo,这一切都会很熟悉。如果您还没有,请记住 a 的任何子级Provider,在我们的例子中是ApolloProvider,都可以访问其给定的功能。 

以下代码是我们新建的 App.js 文件,它是从我们的index.js入口点导入的主要组件。

import React from 'react'
import Tabs from './src/Tabs'

import AWSAppSyncClient from "aws-appsync";
import { Rehydrated } from 'aws-appsync-react';
import { ApolloProvider } from 'react-apollo';

import appSyncConfig from './aws-exports';

const client = new AWSAppSyncClient({
  url: appSyncConfig.graphqlEndpoint,
  region: appSyncConfig.region,
  auth: {
    type: appSyncConfig.authType,
    apiKey: appSyncConfig.apiKey,
  }
});

const WithProvider = () => (
  <ApolloProvider client={client}>
    <Rehydrated>
      <Tabs />
    </Rehydrated>
  </ApolloProvider>
);

export default WithProvider

AWSAppSyncClient在此文件中,我们将结合使用构造函数 fromaws-appsync以及aws- exports.js 文件中的配置来设置新的 AppSync 客户端,该文件提供 GraphQL API URL、区域、身份验证类型和身份验证 API 密钥。

然后,我们将主入口点(将保存我们的选项卡导航的Tabs.js文件)包装在 an ApolloProvider中,并将 AppSync 客户端作为客户端属性传入。我们还将组件包装在Tabs我们Rehydrated从中导入的组件中aws-appsync-react这将确保我们已经从异步存储中读取并在渲染 UI 之前重新水化了我们的缓存。

现在我们的应用程序将能够从我们的 AppSync 端点查询数据,还可以执行突变和订阅!

导航

该应用程序的主要入口点是一个选项卡式导航,在 Tabs.js 文件中使用 React Navigation 实现。

我们在这里所做的是TabNavigator使用两个选项卡创建和导出 a。这些是:

  1. Cities:这个组件列出了我们的城市,它本身就是一个导航器组件。这个组件是一个导航器,因为我们希望能够导航到每个单独的城市并查看城市内的位置。

  2. AddCity:这个组件是我们能够添加新城市的表单。

使用GraphQL、React Native和AWS AppSync编写应用程序:应用程序  第4张

可重用组件

这个应用程序只有一个可重用的组件,一个自定义的TextInput由于我们将一遍又一遍地复制这种风格和功能,我们决定将其作为自己的组件。输入组件在 Input.js中实现。

城市列表和城市导航

该应用程序的主视图是我们将从 GraphQL 检索的城市列表。我们希望能够从每个列出的城市导航到该城市的详细视图,我们可以在其中添加位置。

为此,我们将Cities.js 设为自己的 StackNavigator,并将City.js 设为我们在选择城市时导航到的组件。当点击 中的城市时Cities,我们将其名称和 id 作为道具传递给City.

城市.js

在这个组件中,我们使用查询fetchlistCities,并且我们还订阅 NewCitySubscription,因此当添加新城市时,即使是来自另一个客户端,我们也将处理该订阅并更新我们的城市数组。该 listCities 查询使我们的组件中可用的城市数组为this.props.cities.

城市.js

在这个组件中,我们通过一个城市作为导航的道具(可用)。我们使用 city值通过查询获取所选城市的位置列表 我们订阅新位置的方式与我们在Cities.js中订阅新城市的方式类似,使用 订阅。我们还提供 添加新城市时的 功能。 props.navigation.state.params.cityidlistLocationsNewLocationSubscriptionoptimisticResponseupdate

添加城市

最后,我们需要在 AddCity.js 文件中实现向 GraphQL API 添加新城市的功能。为此,我们将一个突变与一个将调用的表单连接起来 createCity,传递表单输入的值。

AddCity 有一个onAdd我们在 GraphQL com位置中定义的函数,它不仅将一个新城市写入我们的 GraphQL 数据库,而且还使用optimisticResponse和的组合实现了一个乐观的 UI update

突变、查询和订阅

突变、查询和订阅是与我们的 GraphQL API 集成的核心功能。在我们的应用程序中,此功能使用 AppSync 客户端在Cities.jsCity.jsAddCity.js文件中实现。

让我们仔细看看突变、查询和订阅是如何在我们的代码中实现的。

查询

首先,让我们看看如何创建和导出可以与 AppSync Schema 中的 listCities 查询交互的GraphQL查询。此代码包含在src/queries/ListCities.js文件中。

import gql from 'graphql-tag';

export default gql`
query listCities {
  listCities  {
    items {
      name
      country
      id
    }
  }
}`

接下来,我们在Cities.js文件中导入此查询,以及一些帮助程序 from  ,并使用 和 react-apollo连接我们希望访问此数据的组件  from  composegraphqlreact-apollo

import { compose, graphql } from 'react-apollo'
import ListCities from './queries/ListCities'

class Cities extends React.Component {
  // class definition here
  // now have access to this.props.cities
}

export default compose(
  graphql(ListCities, {
      props: props => ({
        cities: props.data.listCities ? props.data.listCities.items : [],
      })
  })
)(CityList)

现在我们可以从我们的 GraphQL 服务器作为 props 访问城市数组。我们可以 this.props.cities 用来映射来自 GraphQL 的城市数组。

突变

要创建一个突变,首先我们需要创建一个基本的 GraphQL 突变并将其导出。我们在 src/mutations/CreateCity.js 文件中执行此操作。

import gql from 'graphql-tag'

export default gql`
  mutation addCity($name: String!, $country: String!, $id: ID!) {
    createCity(input: {
      name: $name, country: $country, id: $id
    }) {
      name
      country
      id
    }
  }
`

现在我们可以在AddCity.js文件中导入这个突变(连同 Apollo 助手)  并在组件中使用它: 

import { compose, graphql } from 'react-apollo'
import AddCityMutation from './mutations/AddCity'

class AddCity extends React.Component {
  // class definition here
  // now have access to this.props.onAdd()
}

export default compose(
  graphql(AddCityMutation, {
    props: props => ({
      onAdd: city => props.mutate({
        variables: city
      })
    })
  })
)(AddCity)

现在,我们可以访问一个名为 的道具 onAdd,我们将一个我们想要发送给突变的对象传递给它!

订阅

订阅允许我们订阅数据更改并让它们在我们的应用程序中实时更新。如果我们要通过添加或删除一个城市来更改我们的数据库,我们希望我们的应用程序能够实时更新。

首先,我们需要创建突变并将其导出,以便我们可以在客户端中访问它。我们将其保存在 src/subscriptionsNewCitySubscriptions.js 文件中。

import gql from 'graphql-tag'

export default gql`
subscription NewCitySub {
  onCreateCity {
    name
    country
    id
  }
}`;

现在我们可以在 Cities.js中导入并附加订阅。我们已经研究了如何从我们的 API 中获取城市。现在让我们更新此功能以订阅新更改并在添加新城市时更新城市数组。

import AllCity from './queries/AllCity'
import NewCitiesSubscription from './subscriptions/NewCitySubscription';
import { compose, graphql } from 'react-apollo'


class Cities extends React.Component {
  componentWillMount(){
    this.props.subscribeToNewCities();
  }
  render() {
    // rest of component here
  }
}

export default compose(
  graphql(ListCities, {
    options: {
      fetchPolicy: 'cache-and-network'
    },
    props: (props) => {
      return {
        cities: props.data.listCities ? props.data.listCities.items : [],
        subscribeToNewCities: params => {
          props.data.subscribeToMore({
            document: NewCitiesSubscription,
            updateQuery: (prev, { subscriptionData: { data : { onCreateCity } } }) => {
              return {
                ...prev,
                listCities: {
                  __typename: 'CityConnection',
                  items: [onCreateCity, ...prev.listCities.items.filter(city => city.id !== onCreateCity.id)]
                }
              }
            }
          })
        }
      }
    }
  })
)(Cities)

我们添加了一个名为 的新道具 subscribeToNewCities, 我们将其称为componentDidMount在订阅中,我们传入一个文档(订阅定义)并 updateQuery 描述我们希望在更新时发生什么。

我们从传递给函数的道具中解构 createCity (包含突变)  updateQuery ,并返回所有现有值以及 listCities  包含先前城市的更新数组以及我们从中获得的新城市数据 createCity

乐观的用户界面

如果我们不想等待订阅从我们的 API 返回最新数据以更新我们的 UI,该怎么办?

import { compose, graphql } from 'react-apollo'
import AddCityMutation from './mutations/AddCity'

class AddCity extends React.Component {
  // class definition here
  // now have access to this.props.onAdd()
}

export default compose(
  graphql(AddCityMutation, {
    props: props => ({
      onAdd: city => props.mutate({
        variables: city,
        optimisticResponse: {
          __typename: 'Mutation',
          createCity: { ...city,  __typename: 'City' }
        },
        update: (proxy, { data: { createCity } }) => {
          const data = proxy.readQuery({ query: ListCities });
          data.listCities.items.unshift(createCity);
          proxy.writeQuery({ query: ListCities, data });
        }
      })
    })
  })
)(AddCity)

在这里,我们向 mutate 函数参数对象添加了两个新属性:

  1. optimisticResponse 定义您希望在更新功能中可用的新响应。

  2. update 接受两个参数,代理(它允许你从缓存中读取)和你想用来进行更新的数据。我们读取当前的缓存proxy.readQuery

结论

GraphQL 正变得越来越主流。围绕 GraphQL 的许多复杂性与管理后端和 API 层有关。然而,像 AppSync 这样的工具将这种复杂性抽象化,让开发人员无需花费大部分时间来配置和处理服务器。

文章目录
  • 应用架构和文件夹结构概述
  • 创建和配置 React Native 客户端
  • 配置提供者和存储
  • 导航
  • 可重用组件
  • 城市列表和城市导航
    • 城市.js
    • 城市.js
  • 添加城市
  • 突变、查询和订阅
    • 查询
    • 突变
    • 订阅
    • 乐观的用户界面
  • 结论