发布于 2026-01-06 6 阅读
0

AWS Amplify 和 React Native 完整指南 目录 01. 简介 02. 项目设置 03. 添加 Cognito 身份验证 04. 添加 AppSync API 05. 添加 S3 存储 06. 获取 AppSync 数据 07. 总结 由 Mux 呈现的 DEV 全球展示挑战赛:展示你的项目!

AWS Amplify 和 React Native 完全指南

目录

01. 引言

02. 项目设置

03. 添加 Cognito 身份验证

04. 添加 AppSync API

05. 添加 S3 存储

06. 获取 AppSync 数据

07. 结论

由 Mux 主办的 DEV 全球展示挑战赛:展示你的项目!

让我们用 ReactNative 和 Amplify 构建一个电子商务应用

点击这里观看视频演示。

目录

  1. 介绍

  2. 项目设置

  3. 添加 Cognito 身份验证

  4. 添加 AppSync API

  5. 添加 S3 存储

  6. 检索 AppSync 数据

  7. 结论

01. 引言

您好!欢迎阅读这篇关于 AWS Amplify 和 React Native 的完整指南。在本教程中,我们将构建一个简单的电子商务应用程序。用户可以登录/注册此应用程序,添加自己的产品,所有用户都可以查看其他用户添加的产品。

这里做一个简单的演示,


移动应用中的不同屏幕

虽然这个应用并不复杂,但它将是一个完美的入门项目。我们将使用不同的 AWS 服务,例如 S3 存储、AWS AppSync API 和 Amazon Cognito 身份验证。别担心,稍后我会详细解释这些服务。

架构图

下图展示了我们的 AWS 架构图。


移动应用的 AWS 架构图

AWS Amplify 让使用这些不同的服务变得更加轻松。和以往一样,我们的后端资源将由 Amplify 创建和管理。下面我将解释这些服务的功能。

因此,Amplify 是我们后端环境的核心。图中从 Amplify 指向的箭头表示我们将使用 Amplify 连接不同的资源。每个产品都会有一张图片,我们会将图片存储在S3存储桶中。产品详情将保存在 Amazon DynamoDB中,这是一个由 AWS 提供的 NoSQL 数据库。为了与该数据库通信,我们将使用 AWS AppSync提供的 GraphQL API。Amazon Cognito 将负责处理身份验证。

准备好开发应用了吗?让我们开始吧!👷🏽‍♂️🧰

先决条件

为避免将来出现任何故障,请确保已安装以下必备组件。

02. 项目设置

安装和配置 Amplify CLI

本教程将指导您使用 AWS Amplify CLI。您可以通过运行以下命令安装它:



npm install -g @aws-amplify/cli@4.39.0


Enter fullscreen mode Exit fullscreen mode

接下来,您需要运行命令amplify configure。这将设置您的 Amplify CLI。您将在其中设置一个新的 IAM 用户。您需要提供 IAM 用户的用户名accessKeyId和密码才能完成secretAccessKeyIAM 用户的设置。

如果您在安装过程中遇到任何问题,可以参考这篇关于安装 Amplify CLI 的原始指南:https://docs.amplify.aws/cli/start/install

创建一个新的 ReactNative 应用程序

希望您已经安装并配置了 Amplify CLI。

要使用 ReactNative,您需要设置 Android 开发环境。您可以参考这篇官方指南:https://reactnative.dev/docs/environment-setup

让我们创建一个名为 AmplifyShop 的新 React Native 应用。



npx react-native init amplify_shop


Enter fullscreen mode Exit fullscreen mode

如果您已经安装了react-native-cli,则可以使用该安装的版本代替npx

使用 Android Studio 打开新建的 React Native 项目。使用 Android Studio 的 AVD 管理器打开 Android 模拟器。在项目目录中,运行以下两个命令。



npx react-native start 
npx react-native run-android


Enter fullscreen mode Exit fullscreen mode

现在,React Native 项目应该可以在您的 Android 模拟器上运行了。如果您遇到任何问题,请参考我之前提供的指南。

初始化 Amplify 后端

让我们先初始化项目的 Amplify 接口。然后我们可以逐个添加服务。

在项目目录中,运行



amplify init


Enter fullscreen mode Exit fullscreen mode

然后系统会提示您输入有关您初始化的项目的以下信息。


运行“amplify init”

初始化 Amplify 项目时,

  • 它会在 src 目录下创建一个名为 的文件aws-exports.js。该文件将存储所有相关信息,用于识别将来要分配的 AWS 资源/服务。

  • 它会创建一个名为 `<directory_name>` 的目录amplify。我们将使用此目录来存储将来要使用的服务的模板和配置详情。Amplify 也会将我们的后端架构保存在此目录中。

  • 它会创建一个云项目。可以使用该amplify console命令查看该项目。

接下来,我们需要运行以下命令来安装所有必要的依赖项。



npm install aws-amplify aws-amplify-react-native amazon-cognito-identity-js @react-native-community/netinfo


Enter fullscreen mode Exit fullscreen mode

您还需要安装 iOS 的 pod 依赖项。



npx pod-install


Enter fullscreen mode Exit fullscreen mode

配置 Amplify 后端

要完成 Amplify 项目的设置,我们需要在高阶组件中配置 Amplify。在您的 `.htm.js`App.js或 `.htm.js`index.js文件中添加以下代码即可。



import Amplify from 'aws-amplify';
import awsconfig from './aws-exports';

Amplify.configure({
  ...awsconfig,
  Analytics: {
    disabled: true,
  },
});


Enter fullscreen mode Exit fullscreen mode

项目设置到此完成。现在我们逐一添加这些服务。

03. 添加 Cognito 身份验证

现在,使用 Amplify 为您的 React Native 应用添加身份验证功能变得前所未有的简单。

添加注册和登录功能

在项目目录中运行amplify add auth。配置身份验证时,请提交以下信息。


运行“amplify add auth”

然后运行命令来部署后端更改。Amplify 将通过创建Cognito 用户池amplify push来处理其余工作

由 Amplify Framework 提供的身份验证 UI 组件将提供完整的身份验证流程。

App.js文件中,

  • 导入withAuthenticator组件


import { withAuthenticator } from 'aws-amplify-react-native'


Enter fullscreen mode Exit fullscreen mode
  • 用组件包裹主组件withAuthenticator


export default withAuthenticator(App)


Enter fullscreen mode Exit fullscreen mode

运行应用后,将显示此登录界面。请尝试以新用户身份登录。这将带您进入主页。新创建的用户将保存到我们的 Cognito 用户池中。


Amplify 的登录界面

在添加 AppSync API 之前,让我们先为应用程序添加导航功能。

添加 ReactNative 导航

我们的应用程序将包含两个屏幕。一个屏幕用于显示产品列表,另一个屏幕用于添加新产品。让我们来创建这两个屏幕。

创建一个名为 `<directory_name>` 的新目录src。在该目录中,创建一个名为 `<folder_name>` 的文件夹screens。在该文件夹中src/screens,创建两个名为 `<javascript_file_name>`add-product-screen.js和`<javascript_file_name>` 的新 JavaScript 文件home-screen.js。我个人比较喜欢这种命名方式,但您可以使用任何命名方式。

复制并粘贴以下示例代码。请根据页面内容更改函数名称(“HomeScreen”和“AddProductScreen”)和标题。

目录:src/screens/ home.js,add-product-screen.js



import React from 'react';
import {SafeAreaView, StatusBar, Text} from 'react-native';

const HomeScreen = (props) => {
  return (
    <>
      <StatusBar barStyle="dark-content" />
      <SafeAreaView>
        <Text>Home</Text>
      </SafeAreaView>
    </>
  );
};

export default HomeScreen;


Enter fullscreen mode Exit fullscreen mode

在 React Native 应用中添加导航有多种方法。本教程将使用 React Navigation 中的“Stack Navigator Library”。首先,我们需要使用 npm 安装它。



npm install @react-navigation/native


Enter fullscreen mode Exit fullscreen mode

同时安装所有其他第三方依赖项。



npm install react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view @react-navigation/stack


Enter fullscreen mode Exit fullscreen mode

从 React Native 0.60 及更高版本开始,链接是自动的。因此,您无需运行react-native link

如果你使用的是 Mac 电脑,并且正在为 iOS 开发应用,则需要安装 pods(通过Cocoapods)来完成链接。



npx pod-install ios


Enter fullscreen mode Exit fullscreen mode

App.js要完成 React Native Navigation 的安装,请在您的或index.js文件中添加以下导入语句。



import 'react-native-gesture-handler';


Enter fullscreen mode Exit fullscreen mode

为了本教程的目的,我将使用两个额外的样式库。我将使用react-native-elementsreact-native-vector-icons。让我们使用 npm 安装它们。



npm install react-native-elements
npm install react-native-vector-icons


Enter fullscreen mode Exit fullscreen mode

为了查看fontawesome icons,我们需要在 android/app/ build.gradle文件中添加以下行。



apply from: "../../node_modules/react-native-vector-icons/fonts.gradle"


Enter fullscreen mode Exit fullscreen mode

完成上述步骤后,请转到App.js文件。我们将使用该App.js文件来设置应用程序中的导航。请将当前代码替换为以下代码。

目录:App.js



import React from 'react';
import {StyleSheet, View, TouchableOpacity} from 'react-native';
import {createStackNavigator} from '@react-navigation/stack';
import {NavigationContainer} from '@react-navigation/native';
import AddProductScreen from './src/screens/add-product-screen';
import HomeScreen from './src/screens/home-screen';
import {Button} from 'react-native-elements';
import Icon from 'react-native-vector-icons/FontAwesome';
import {withAuthenticator} from 'aws-amplify-react-native';

const App: () => React$Node = () => {
  const Stack = createStackNavigator();
  return (
    <>
      <NavigationContainer>
        <Stack.Navigator initialRouteName="Home">
          <Stack.Screen
            name="Home"
            component={HomeScreen}
            options={({navigation}) => ({
              title: 'Home',
              headerStyle: {
                backgroundColor: '#ff9300',
              },
              headerRight: () => (
                <TouchableOpacity
                  style={styles.addButton}
                  onPress={() => navigation.navigate('AddProduct')}>
                  <Icon name={'plus'} size={20} color="#000000" />
                </TouchableOpacity>
              ),
            })}
          />
          <Stack.Screen
            name="AddProduct"
            buttonStyle={styles.addButton}
            component={AddProductScreen}
            options={{
              title: 'Add Product',
              headerStyle: {
                backgroundColor: '#ff9300',
              },
            }}
          />
        </Stack.Navigator>
      </NavigationContainer>
    </>
  );
};
const styles = StyleSheet.create({
  addButton: {
    marginRight: 20,
  },
  logOutBtn: {
    marginLeft: 10,
  },
});

export default withAuthenticator(App);


Enter fullscreen mode Exit fullscreen mode

这是添加导航最简单便捷的方法。我们创建了Stack.Navigator一个组件,可以为其提供初始路由。在这个包装组件内部,我们可以使用Stack.Screen其他组件来定义每个屏幕。

我们可以使用这个options属性来定义每个屏幕的头部。我刚刚在头部右侧添加了一个导航按钮,它应该会跳转到“添加产品”屏幕。

由于我们使用的是堆叠式导航,新屏幕会加载在前一个屏幕之上。因此,返回按钮会自动添加。

添加登出选项

不如在主屏幕上添加一个注销选项。我们已经headerRight向主屏幕传递了元素,可以再传递一个名为 `signout` 的属性headerLeft。这样会在标题栏左侧创建一个新按钮。

请将以下代码与导入语句一起粘贴进去。



// importing Auth Class from Amplify Library
import {Auth} from 'aws-amplify';
headerLeft: () => (
  <View style={styles.logOutBtn}>
    <Button
      icon={<Icon name="sign-out" size={25} color="#000000" />}
      onPress={}
      type="clear"
    />
  </View>
),


Enter fullscreen mode Exit fullscreen mode

点击“注销”按钮将触发Auth.signOut()一个方法。该方法将结束用户的登录会话。会话结束后,登录界面将自动加载。我们无需管理任何状态变量。Amplify 将负责身份验证会话的处理。

好了,导航部分就到这里。点击此处了解更多关于 React Native 导航的信息。最终结果应该类似于这样。


添加导航后

04. 添加 AppSync API

让我们通过添加 AppSync API 来存储产品详情。我们将保存产品的名称、价格和描述等信息。我们还会为每个产品添加图片。图片功能我们稍后再处理。

执行“amplify add api”

正如我之前所说,通过 AppSync,我们可以构建GraphQL API。所有繁重的工作,例如连接和创建 DynamoDB 表、生成查询和变更操作,都将由AppSync完成。

首先,我们为 Amplify 后端配置一个 AppSync API。执行以下命令:



amplify add api


Enter fullscreen mode Exit fullscreen mode

您将被要求提供以下信息。


运行“amplify add api”

接受默认设置即可。

编辑 GraphQL Schema

让我们来编辑我们的模式文件。您可以schema.graphql在该目录中找到该文件amplify/backend/api/schema.graphql。复制并粘贴以下模式文件。



type Product
@model(subscriptions: null)
@auth(
  rules: [
    { allow: owner },
    { allow: private, operations: [read] }
  ]) {
  id: ID!
  name: String!
  description: String
  price: Float
  userId: String
  userName: String
  image: String
}


Enter fullscreen mode Exit fullscreen mode

保存文件。然后执行部署操作amplify push,将更改部署到 AWS 云。


添加 AppSync API 后运行“amplify push”

现在,我们的 AppSync API 已创建完成。此外,AppSync 库还自动为我们的 GraphQL Schema 创建了查询和变更。运行命令amplify api console即可在 AWS 中查看您的 AppSync API。

您可以在此 AWS AppSync 控制台中尝试一些 GraphQL 操作。


AWS AppSync 控制台

添加产品屏幕

让我们开始与 AppSync API 进行交互。

在此之前,我想添加一个额外的包,它可以帮助创建 React Native 表单。使用tcomb-form-native包,您可以快速动态地创建表单。那么,让我们使用 npm 安装它。



npm install tcomb-form-native


Enter fullscreen mode Exit fullscreen mode

复制以下代码并粘贴到我们的 add-product-screen.js 文件中。

目录:src/screens/add-product-screen.js



import React, {useState} from 'react';
import {StyleSheet, SafeAreaView, ScrollView} from 'react-native';
import {Button} from 'react-native-elements';
import t from 'tcomb-form-native';
const Form = t.form.Form;
const User = t.struct({
  name: t.String,
  price: t.Number,
  description: t.String,
});
const AddProductScreen = ({navigation}) => {
  const [form, setForm] = useState(null); 
  const [initialValues, setInitialValues] = useState({});

  const options = {
    auto: 'placeholders',
    fields: {
      description: {
        multiLine: true,
        stylesheet: {
          ...Form.stylesheet,
          textbox: {
            ...Form.stylesheet.textbox,
            normal: {
              ...Form.stylesheet.textbox.normal,
              height: 100,
              textAlignVertical: 'top',
            },
          },
        },
      },
    },
  };
const handleSubmit = async () => {
    // Saving product details
  };
return (
    <>
      <SafeAreaView style={styles.addProductView}>
        <ScrollView>
          <Form
            ref={(c) => setForm(c)}
            value={initialValues}
            type={User}
            options={options}
          />
          <Button title="Save" onPress={handleSubmit} />
        </ScrollView>
      </SafeAreaView>
    </>
  );
};
const styles = StyleSheet.create({
  addProductView: {
    display: 'flex',
    flexDirection: 'column',
    justifyContent: 'center',
    paddingTop: 15,
    height: 'auto',
  },
});
export default AddProductScreen;


Enter fullscreen mode Exit fullscreen mode

尝试运行你的应用,你应该会看到一个类似这样的表单。

让我们来检查一下代码。

你可以看到,我没有使用任何 `<T>` 标签textInputs。我只是用 `<T>` 标签定义了我们的字段t.struct,并且由于描述是多选的textInput,我们需要传入额外的选项。

我们的handleSubmit函数会将输入的信息保存到数据库中。请将以下代码粘贴到我们的handleSubmit函数中。别忘了导入必要的库。



import { Auth, API, graphqlOperation} from 'aws-amplify';
import {createProduct} from '../../graphql/mutations';

try {
      const value = await form.getValue();
      const user = await Auth.currentAuthenticatedUser();
const response = await API.graphql(
        graphqlOperation(createProduct, {
          input: {
            name: value.name,
            price: value.price.toFixed(2),
            description: value.description,
            userId: user.attributes.sub,
            userName: user.username,
          },
        }),
      );
      console.log('Response :\n');
      console.log(response);
    } catch (e) {
      console.log(e.message);
    }


Enter fullscreen mode Exit fullscreen mode

Auth.currentAuthenticatedUser()顾名思义,该函数会返回已登录用户的详细信息。Cognito 为每个用户提供一个名为 `userId` 的属性sub,这是一个唯一的字符串值。我们将把该值保存为分配给产品的 `userId`。`Username` 将显示产品所有者。

createProduct突变是自动生成的。这里我们指的是graphql/mutations.js文件中定义的那个突变。

现在,运行应用并保存产品后,您应该会在 console.log 中看到响应信息。您也可以在 AWS AppSync 控制台中查询。

05. 添加 S3 存储

现在,用户可以保存产品详情了。我们还应该添加上传产品图片的功能。我们需要一个 S3 存储桶来存储产品图片。使用 Amplify 可以大大简化 S3 的使用。让我来演示一下。

在此之前,请安装React Native 图片选择器库



npm install react-native-image-picker


Enter fullscreen mode Exit fullscreen mode

RN >= 0.60
cd ios && pod install

RN < 0.60
react-native 链接 react-native-image-picker

目前,此图像选择器库仅支持 SDK 21 或更新版本。因此,请android/build.gradle文件中编辑minSDK 版本

buildToolsVersion = "29.0.2"
minSdkVersion = 21
compileSdkVersion = 29
targetSdkVersion = 29

执行“amplify add storage”

跑步,



amplify add storage


Enter fullscreen mode Exit fullscreen mode

创建一个新的 S3 存储桶。接受提示中的默认设置。


运行“amplify add storage”

运行amplify push以部署您的更改。

更新表格

让我们在表单中添加图片上传和预览功能。我创建了一个带有图片预览功能的精美 ImageUploader 组件。请确保通过components在文件夹中创建一个新目录来添加它src

目录:src/components/ImageUploader.js



import React from 'react';
import {View, Image, Button, StyleSheet} from 'react-native';

const ImageUploader = ({handleChoosePhoto, photo}) => {
  return (
    <View style={styles.imageView}>
      {photo && <Image source={{uri: photo.uri}} style={styles.photo} />}
      <Button
        style={styles.photoBtn}
        title="Choose Photo"
        onPress={handleChoosePhoto}
      />
    </View>
  );
};

const styles = StyleSheet.create({
  imageView: {
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'center',
    paddingBottom: 15,
  },
  photo: {
    width: 200,
    height: 200,
  },
});

export default ImageUploader;


Enter fullscreen mode Exit fullscreen mode

为了使用此图像上传选项,我们将对add-product-screen.js文件进行以下更改。

我们将在 ScrollView 组件中添加额外的 ImageUploader 组件。



return (
  <>
    <SafeAreaView style={styles.addProductView}>
      <ScrollView>
        <Form
          ref={(c) => setForm(c)}
          value={initialValues}
          type={User}
          options={options}
        />
        <ImageUploader photo={photo} handleChoosePhoto={handleChoosePhoto} />
        <Button title="Save" onPress={handleSubmit} />
      </ScrollView>
    </SafeAreaView>
  </>
);


Enter fullscreen mode Exit fullscreen mode

将此状态变量与新的 handleChoosePhoto 函数一起声明。



const [photo, setPhoto] = useState(null);
const handleChoosePhoto = async () => {
  const product = await form.getValue();

  setInitialValues({
    name: product.name,
    price: product.price,
    description: product.description,
  });
  await launchImageLibrary({}, (response) => {
    // console.log(response.data);
    if (response.uri) {
      console.log('Photo Extension: \n');
      // console.log(response);
      setPhoto(response);
    }
  });
};


Enter fullscreen mode Exit fullscreen mode

如果我们不设置初始值,启动图像库将会重置表单。

别忘了添加这些导入项。



import {launchImageLibrary} from 'react-native-image-picker'; 
import {Storage} from 'aws-amplify';


Enter fullscreen mode Exit fullscreen mode

您可以对该表单进行测试运行。您应该会看到类似这样的内容。


添加产品屏幕

此外,我们也应该更新我们的handleSubmit函数。



const handleSubmit = async () => {
  try {
    const value = await form.getValue();
    console.log('value: ', value);
    const user = await Auth.currentAuthenticatedUser();
    if (photo) {
      const response = await fetch(photo.uri);

      const blob = await response.blob();
      console.log('FileName: \n');
      await Storage.put(photo.fileName, blob, {
        contentType: 'image/jpeg',
      });
    }
    const response = await API.graphql(
      graphqlOperation(createProduct, {
        input: {
          name: value.name,
          price: value.price.toFixed(2),
          description: value.description,
          userId: user.attributes.sub,
          userName: user.username,
          image: photo.fileName,
        },
      }),
    );
    console.log('Response :\n');
    console.log(response);
    navigation.navigate('Home');
  } catch (e) {
    console.log(e.message);
  }
};


Enter fullscreen mode Exit fullscreen mode

我们可以使用 AWS Amplify 库提供的方法将 S3 镜像上传到我们的存储桶中Storage.put。我们需要文件名(S3 中的镜像键)才能再次访问该文件。因此,我们会将其存储在数据库中。

尝试上传一张新图片。提交表单。等待图片上传完成。你应该会看到类似这样的 console.log 输出。



    [Sat Jan 02 2021 01:58:21.981]  LOG      Response :

    [Sat Jan 02 2021 01:58:21.982]  LOG      {"data": {"createProduct": {"createdAt": "2021-01-01T20:28:22.382Z", "description": "About Sahan New Product", "id": "f3188508-5ee7-4af4-acf3-3c948f61d868", "image": "6ca2947e-766b-445e-b260-0041502e652a", "name": "Sahan New Product", "price": 200, "updatedAt": "2021-01-01T20:28:22.382Z", "userId": "7d5fa0a3-4d26-4354-8028-7cc597a69447", "userName": "sahan"}}}


Enter fullscreen mode Exit fullscreen mode

06. 获取 AppSync 数据

现在,让我们在主屏幕上显示产品列表视图。为此,我创建了两个新组件,

  • 产品卡组件

目录:src/components/ProductCard.js



import React, {useEffect, useState} from 'react';
import {Text, StyleSheet, View} from 'react-native';
import {Card, Icon, Image} from 'react-native-elements';
import {Storage} from 'aws-amplify';

const ProductCard = ({
  productName,
  productOwner,
  productPrice,
  productImage,
}) => {
  const [imageSource, setImageSource] = useState(null);
  const getImage = async () => {
    try {
      const imageURL = await Storage.get(productImage);
      setImageSource({
        uri: imageURL,
      });
    } catch (e) {
      console.log(e);
    }
  };
  useEffect(() => {
    getImage();
  }, []);
  return (
    <Card containerStyle={styles.cardContainer}>
      <Card.Title style={styles.cardTitle}>{productName}</Card.Title>
      <Card.Divider />
      {imageSource && (
        <Image source={imageSource} style={styles.productImage} />
      )}
      {!imageSource && (
        <View style={styles.altView}>
          <Text>Product Image</Text>
        </View>
      )}
      <Text style={styles.productPrice}>{productPrice}$</Text>
      <View style={styles.ownerTitle}>
        <Icon name="person-pin" />
        <Text style={styles.productOwner}>{productOwner}</Text>
      </View>
    </Card>
  );
};
const styles = StyleSheet.create({
  cardContainer: {
    marginBottom: 20,
    shadowColor: '#000',
    shadowOffset: {
      width: 0,
      height: 2,
    },
    shadowOpacity: 0.25,
    shadowRadius: 3.84,

    elevation: 5,
  },
  productImage: {
    width: 200,
    height: 200,
    alignSelf: 'center',
  },
  productPrice: {
    marginTop: 10,
    marginBottom: 10,
    fontSize: 16,
    fontWeight: 'bold',
  },
  altView: {
    width: 200,
    height: 200,
    display: 'flex',
    flexDirection: 'column',
    justifyContent: 'center',
  },
  cardTitle: {
    fontSize: 20,
  },
  productOwner: {
    fontSize: 16,
    fontWeight: 'bold',
    alignSelf: 'center',
  },
  ownerTitle: {
    display: 'flex',
    flexDirection: 'row',
    justifyContent: 'flex-end',
  },
});
export default ProductCard;


Enter fullscreen mode Exit fullscreen mode
  • 产品列表组件

目录:src/components/ProductList.js



import React from 'react';
import {View, Text, FlatList, StyleSheet, RefreshControl} from 'react-native';

import ProductCard from './ProductCard';

const ProductList = ({productList, refreshing, onRefresh}) => {
  return (
    <View style={styles.productsView}>
      {productList && (
        <FlatList
          style={styles.productList}
          refreshControl={
            <RefreshControl refreshing={refreshing} onRefresh={onRefresh} />
          }
          keyExtractor={(item) => item.id}
          data={productList}
          renderItem={({item}) => {
            return (
              <ProductCard
                productName={item.name}
                productImage={item.image}
                productOwner={item.userName}
                productPrice={item.price}
              />
            );
          }}
        />
      )}
    </View>
  );
};

const styles = StyleSheet.create({
  itemText: {
    fontSize: 15,
  },
  productText: {
    fontSize: 20,
    fontWeight: 'bold',
    alignSelf: 'center',
  },
  productsView: {
    padding: 0,
    margin: 0,
    display: 'flex',
    flexDirection: 'column',
    justifyContent: 'center',
    alignItems: 'center',
  },
  productList: {
    padding: 5,
    marginBottom: 20,
  },
});
export default ProductList;


Enter fullscreen mode Exit fullscreen mode

现在,让我们在主屏幕中使用此产品列表组件。请将当前示例代码替换为以下代码。

目录:src/screens/home-screen.js



import React, {useEffect, useState} from 'react';
import {API} from 'aws-amplify';
import {SafeAreaView, StatusBar, TouchableOpacity} from 'react-native';

import {listProducts} from '../../graphql/queries';
import ProductList from '../components/ProductList';
const HomeScreen = (props) => {
  const [productsList, setProducts] = useState([]);
  const [refreshing, setRefreshing] = useState(false);

  const fetchProducts = async () => {
    try {
      const products = await API.graphql({query: listProducts});
      if (products.data.listProducts) {
        console.log('Products: \n');
        console.log(products);
        setProducts(products.data.listProducts.items);
      }
    } catch (e) {
      console.log(e.message);
    }
  };
  useEffect(() => {
    fetchProducts();
  }, []);

  const onRefresh = async () => {
    setRefreshing(true);
    await fetchProducts();
    setRefreshing(false);
  };
  return (
    <>
      <StatusBar barStyle="dark-content" />
      <SafeAreaView>
        {productsList && (
          <ProductList
            productList={productsList}
            refreshing={refreshing}
            onRefresh={onRefresh}
          />
        )}
      </SafeAreaView>
    </>
  );
};

export default HomeScreen;


Enter fullscreen mode Exit fullscreen mode

在主屏幕的 useEffect 钩子函数中,我们正在获取所有产品。这次,我们运行的是一个 GraphQL 查询listProducts,该查询将在文件中自动定义graphql/queries.js

我们将获取到的产品信息传递给产品列表组件。产品列表组件会为每个产品渲染一张产品卡片。

在产品卡片组件中,当我们把图片文件名传递给Storage.get函数时,我们会得到完整的图片 URL。

尝试运行您的应用,现在应该可以看到您的产品列表了。


主屏幕

07. 结论

这样一来,我们就成功完成了所有功能。那么,让用户订购产品怎么样?这部分就留给你们自己尝试吧😃。

恭喜你完成教程!🎉

如果我们回顾一下我们已经做的事情,

  1. 我们添加了 Cognito 身份验证,以便用户登录或注册我们的应用程序。

  2. 此外,我们还加入了导航和注销选项。

  3. 我们创建了 AppSync GraphQL API,并将一些产品详细信息保存到了我们的数据库中。

  4. 我们创建了 S3 存储桶,让用户可以为每个产品上传图片。

  5. 在主屏幕上,我们可以向用户显示产品列表视图。

我想现在你已经很好地了解如何在 ReactNative 应用中使用这些不同的 AWS 资源了。

希望您已顺利完成所有步骤,没有遇到任何问题。如果您遇到任何问题,都可以在下方评论区留言。

本文相关的视频演示:

AWS Amplify 和 React Native 速成课程

文章来源:https://dev.to/dev_sahan/complete-guide-to-aws-amplify-and-react-native-4on5