react全栈_如何使用React和Ampl构建全栈无服务器应用程序

曹臻
2023-12-01

react全栈

With emerging cloud technologies, like Amplify and Azure functions, it is now easier than ever to build production ready, robust, and scalable modern web applications.

借助新兴的云技术(例如Amplify和Azure功能),现在比以往任何时候都更容易构建生产就绪,健壮且可扩展的现代Web应用程序。

Developers can implement Authentication, APIs, data layers, machine learning, chatbots, even AR scenes more easily than ever by taking advantage of these new serverless cloud technologies.

利用这些新的无服务器云技术,开发人员可以比以往更轻松地实现身份验证,API,数据层,机器学习,聊天机器人,甚至AR场景。

In this practical guide I will walk you through building your very first full stack serverless application with React and AWS Amplify. I will walk you through some of the key concepts of AWS Amplify and React while building a sample application similar to reddit or hacker news.

在本实用指南中,我将指导您使用React和AWS Amplify构建您的第一个全栈无服务器应用程序。 在构建类似于reddit或hacker news的示例应用程序时,我将向您介绍AWS Amplify和React的一些关键概念。

We will cover the following topics.

我们将涵盖以下主题。

  1. Configuring AWS Amplify ️

    配置AWS Amplify️
  2. Adding a Serverless API to a React App 隣

    将无服务器API添加到React App隣
  3. User Authentication with Cognito  ‍

    使用Cognito的用户身份验证
  4. GraphQL queries 

    GraphQL查询

The full source code for the completed project can be found at this link:

可以在以下链接中找到完整项目的完整源代码:

Complete Code Here

Here这里完整的代码

配置AWS Amplify (Configuring AWS Amplify)

先决条件: (Prerequisites:)

Before continuing make sure you have the following configured.

在继续之前,请确保已配置以下内容。

  1. AWS account (Free Tier)

    AWS账户(免费套餐)
  2. Node.js 10.x or higher installed on your pc

    您的PC上安装了Node.js 10.x或更高版本
  3. Npm 6.9.0. or higher

    Npm 6.9.0。 或更高
  4. Git installed on your pc

    安装在电脑上的Git

First of all we need to install the amplify cli. We can do this by running the following command:

首先,我们需要安装amplify cli 。 我们可以通过运行以下命令来做到这一点:

npm install -g @aws-amplify/cli

After the installation is done we can configure amplify by running the following command:

安装完成后,我们可以通过运行以下命令来配置amplify:

amplify configure

It will ask you to sign in to AWS. Once you sign in it will prompt you with the instructions to create an IAM user.

它将要求您登录到AWS。 登录后,它将提示您创建IAM用户的说明。

***Note: IAM stands for (Identity Access Management). You can learn more about it in from this link. ***

***注意:IAM代表(身份访问管理)。 您可以从此链接中了解更多信息。 ***

You will see something similar to the below in your terminal.

您将在终端中看到类似于以下内容的内容。

Specify the AWS Region? 
region:  # Type Your preferred region (for me I choose ca-central)
Specify the username of the new IAM user:
user name:  # User name for Amplify IAM user
Complete the user creation using the AWS console (Y/n)

Select your preferred options. Amplify will the open up a browser tab and you have to login to your AWS console in the browser. Then it will ask you to create a user. Make sure you create the user with administrative privileges.

选择您的首选选项。 Amplify将打开一个浏览器选项卡,您必须在浏览器中登录到AWS控制台。 然后它将要求您创建一个用户。 确保您创建具有管理特权的用户。

**Follow this short video example if you are not sure how to proceed:

**如果不确定如何继续,请遵循以下简短视频示例:

Once the user is created save the accessKeyId and the  secretAccessKey in a secure location. Amplify will ask you to provide these values in the terminal. When you see a user input prompt in the command line enter these values.

创建用户后,将accessKeyIdsecretAccessKey保存在安全的位置。 Amplify将要求您在终端中提供这些值。 当您在命令行中看到用户输入提示时,请输入以下值。

And that’s it. You are now all setup with Amplify.

就是这样。 现在,您都可以使用Amplify进行设置。

创建一个新的React应用 (Creating a new React app)

Now that we are all setup with Amplify, let’s go ahead and create a new React application.

现在我们都已经使用Amplify进行了设置,让我们继续创建一个新的React应用程序。

npx create-react-app serverless-blog
cd serverless-blog
npm start

Alright, we are now ready to add a serverless back-end to our React application.

好了,我们现在准备将无服务器后端添加到我们的React应用程序中。

将无服务器API添加到React (Adding a Serverless API to React)

Adding a serverless API is very simple with Amplify. All we have to do is run the following command and the amplify cli will walk us through the process of API creation.

使用Amplify添加无服务器API非常简单。 我们要做的就是运行以下命令, amplify cli将引导我们完成API创建过程。

In the root of our react app we have to run the following command:

在我们的react应用程序的根目录中,我们必须运行以下命令:

amplify add api

Amplify CLI now will prompt us with some questions:

现在,Amplify CLI会提示我们一些问题:

Please select from one of the below mentioned services: GraphQL # select GraphQL
Provide API name: serverlessblog  # choose a name for your api

Amplify gives us the options to choose REST or GraphQL. For this project we will be choosing GraphQL.

Amplify为我们提供了选择REST或GraphQL的选项。 对于此项目,我们将选择GraphQL。

Moving into the next question it will ask you what type of authorization we would like.

进入下一个问题,它将询问您我们想要哪种授权。

Choose the default authorization type for the API

For this option choose Amazon Cognito User Pool. We will choose this option because in our app we want the users to have the ability to signup, login and logout. We will also only allow signed up users to create posts.

对于此选项,请选择“ Amazon Cognito User Pool 。 我们将选择此选项,因为在我们的应用程序中,我们希望用户能够注册,登录和注销。 我们还将仅允许注册用户创建帖子。

Next we will see a couple more questions. We can choose all the default options for these questions.

接下来,我们将看到另外两个问题。 我们可以为这些问题选择所有默认选项。

Do you want to use the default authentication and security configuration? # Select Default
How do you want users to be able to sign in? # Select Username
Do you want to configure advanced settings? # Select No
Do you want to configure advanced settings for the GraphQL API # Select No
Do you have an annotated GraphQL schema? # Select No
Do you want a guided schema creation? # Select Yes

Finally it will ask you how you would describe your project. For this option select one to many.

最后,它将询问您如何描述您的项目。 对于此选项,选择一对多。

What best describes your project: One-to-many relationship 
(e.g., “Blogs” with “Posts” and “Comments”)

Then the API will be generated. We will see that a folder called Amplify has been generated. Locate the amplify/backend/api/schema.graphql file. This is our schema for the database. Let’s take a look inside of this file.

然后将生成API。 我们将看到已生成一个名为Amplify的文件夹。 找到amplify/backend/api/schema.graphql文件。 这是我们的数据库架构。 让我们看一下这个文件的内部。

type Post @model @auth(
    rules: [
      {allow: owner, ownerField: "owner", operations: [create, update, delete]},
    ]
) {
  id: ID!
  title: String!
  content: String!
  owner: String
  comments: [Comment] @connection(keyName: "byPost", fields: ["id"])
}

type Comment @model @key(name: "byPost", fields: ["postID", "content"]) {
  id: ID!
  postID: ID!
  post: Post @connection(fields: ["postID"])
  content: String!
}

We have two models defined above, a Post model and a Comment model. A model represents a table in our database. By default we are using DynamoDB from Amazon.

我们在上面定义了两个模型,一个Post模型和一个Comment模型。 模型代表我们数据库中的表。 默认情况下,我们使用来自Amazon的DynamoDB。

You can login to AWS console in the browser and take a look at the DynamoDB tables. For our Post model we have mandatory fields id , title and content . The ! symbol represents a mandatory fields. Similarly Comment model also has a couple mandatory fields.

您可以在浏览器中登录到AWS控制台,然后查看DynamoDB表。 对于我们的Post模型,我们具有必填字段idtitlecontent! 符号表示必填字段。 同样, Comment模型也有几个必填字段。

Now, the Post model has a @connection key defined in the comments field. This represents a foreign key join. The foreign key is joined to the id field of the Comment model by a key name byPost .

现在, Post模型在注释字段中定义了一个@connection键。 这表示外键联接。 外键通过键名byPost联接到Comment模型的id字段。

If we look at the Comment model we can see a @key key that is doing the same. This join is create a has_many relationship between two model. Therefore our posts has many comments. If you are familiar with relational databases you probably know this concept.

如果我们查看Comment模型,我们会看到一个@key键正在执行相同的操作。 这种has_many是在两个模型之间创建一个has_many关系。 因此,我们的帖子有很多评论。 如果您熟悉关系数据库,您可能会知道这个概念。

Notice that we have another keyword, @auth. This key ensures ownership. If we look at the rules associated to this key we will see that we are only allowing an owner (an authenticated user) to create, update and delete a record. It will also prevent a user from deleting a post created by some else.

注意,我们还有另一个关键字@auth 。 此密钥可确保所有权。 如果我们查看与此密钥关联的规则,我们将看到我们仅允许所有者(经过身份验证的用户)创建,更新和删除记录。 这也将防止用户删除其他人创建的帖子。

Alright, now let’s push our code to AWS cloud with the following command:

好了,现在让我们使用以下命令将代码推送到AWS云:

Amplify push

Amplify cli will prompt you with an option to choose the code generation language. Choose Javascript. This will generate some code for us. We will be using this generated code for GraphQL queries and mutations.

Amplify cli将提示您选择代码生成语言的选项。 选择Javascript。 这将为我们生成一些代码。 我们将使用此生成的代码进行GraphQL查询和变异。

You can find the code for the project up to this point at the following link:

您可以通过以下链接找到到目前为止的项目代码:

https://github.com/Shadid12/serverless-blog/tree/01-initial-setup

https ://github.com/Shadid12/serverless-blog/tree/01-initial-setup

让我们创建一个主页 (Let’s Create a Home Page )

We would like to have a home page with all the latest posts listed. So let’s go to our src/App.js and create a new Home React component.

我们希望有一个列出所有最新帖子的主页。 因此,让我们转到src/App.js并创建一个新的Home React组件。

// src/App.js

import React from 'react';
import Home from './components/Home'

function App() {
  return (
    <Home />
  );
}

export default App;

We can create a new directory called component and create a new file Home.js for our Home component.

我们可以创建一个名为component的新目录,并为Home组件创建一个新文件Home.js

// src/components/Home.js

import React from 'react';

function Home() {
  const posts = [
      {
          id: 'id-1',
          title: 'dummy title',
          content: 'dummy content'
      },
      {
        id: 'id-2',
        title: 'dummy title 2',
        content: 'dummy content 2'
    }
  ];


  return (
    <div >
      <ul>
          {posts.map(p => (
              <li>
                  <h3><a href="">{p.title}</a></h3>
                  <p>{p.content}</p>
              </li>
          ))}
      </ul>
    </div>
  );
}

export default Home;

We created some hard coded values for posts. We will replace this with an API call later on.

我们为帖子创建了一些硬编码值。 稍后,我们将用API调用替换它。

使用Cognito进行用户身份验证 (User Authentication with Cognito)

Let’s dive into authentication. First of all we need to install a couple npm packages.

让我们深入探讨身份验证。 首先,我们需要安装几个npm软件包。

npm i aws-amplify-react aws-amplify --save

These two packages make it really easy to add user authentication with React. First of all we need to configure the Amplify back end with React. Let’s open up src/index.js file and add the following code:

这两个软件包使使用React添加用户身份验证变得非常容易。 首先,我们需要使用React配置Amplify后端。 让我们打开src/index.js文件并添加以下代码:

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import Amplify from 'aws-amplify';
import aws_export from './aws-exports';

Amplify.configure(aws_export);

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

We are doing a couple things here. First of all we are importing aws_export. This file was generated through Amplify's code generator. This file contains our project metadata. Make sure to always gitignore this file as it contains sensitive data. We then import Amplify instance and call the configure method with aws_export as parameter.

我们在这里做两件事。 首先,我们要导入aws_export 。 该文件是通过Amplify的代码生成器生成的。 此文件包含我们的项目元数据。 确保始终gitignore此文件,因为它包含敏感数据。 然后,我们导入Amplify实例,并使用aws_export作为参数调用configure方法。

Next we will go to our home component and we will import a higher order component called withAuthenticator from aws-amplify-react package. All we have to do it to wrap our Home component with this higher order component to make it authentication protected.

接下来,我们将转到home组件,并从aws-amplify-react包中导入一个名为withAuthenticator的高级组件。 我们要做的就是用这个更高阶的组件包装Home组件,以使其受到身份验证保护。

import React from 'react';
import { withAuthenticator } from 'aws-amplify-react';

function Home() {
  const posts = [
      {
          id: 'id-1',
          title: 'dummy title',
          content: 'dummy content'
      },
      {
        id: 'id-2',
        title: 'dummy title 2',
        content: 'dummy content 2'
    }
  ];


  return (
    <div >
      <ul>
          {posts.map(p => (
              <li>
                  <h3><a href="">{p.title}</a></h3>
                  <p>{p.content}</p>
              </li>
          ))}
      </ul>
    </div>
  );
}

export default withAuthenticator(Home );

That’s pretty much does the trick. Simple and easy. Now if we go to our app we should see a login screen. We are only able to view the Home component when we are logged in.

这几乎可以解决问题。 简单容易。 现在,如果我们转到应用程序,我们应该会看到一个登录屏幕。 登录后,我们只能查看Home组件。

Now that is neat ✨✨. Amplify even created an authentication verification process for us. First time users will receive an email confirmation to verify their account.

现在很整齐。 Amplify甚至为我们创建了一个身份验证过程。 首次用户将收到一封电子邮件确认,以验证其帐户。

GraphQL查询 (GraphQL queries)

经典CRUD (Classic CRUD)

Pretty much every web application has the basic CRUD (Create, Read, Update, Delete) functionality. In our app we’ll have this functionality as well. A user will be able to create, read, update and delete posts and comments.

几乎每个Web应用程序都具有基本的CRUD(创建,读取,更新,删除)功能。 在我们的应用程序中,我们还将具有此功能。 用户将能够创建,阅读,更新和删除帖子和评论。

创建帖子 (Creating a Post)

When our user is logged in they should see a link to create a new post. When the user clicks the link it should take them to a new page with a form. Then the user submits the form and a new post is created.

当我们的用户登录后,他们应该看到一个链接来创建一个新帖子。 用户单击链接时,应将其带到带有表单的新页面。 然后,用户提交表单并创建一个新帖子。

To achieve this we need to be able to route to different links. We’ll be using the react-router-dom package to do the routing.

为此,我们需要能够路由到不同的链接。 我们将使用react-router-dom包进行路由。

Let’s install this package and bring it in our project.

让我们安装此软件包并将其引入我们的项目。

npm i react-router-dom --save

Now, in our App.js file we can modify our code to route into different urls.

现在,在App.js文件中,我们可以修改代码以路由到不同的url中。

import React from 'react';
import Home from './components/Home';
import Post from './components/Post';
import {
  BrowserRouter as Router,
  Switch,
  Route,
  Link
} from "react-router-dom";

function App() {
  return (
    <Router>
      <div>
        <ul>
            <li>
              <Link to="/">Home</Link>
            </li>
            <li>
              <Link to="/posts/new">New Post</Link>
            </li>
         </ul>

          <Switch>
            <Route exact path="/">
              <Home />
            </Route>
            <Route path="/posts/new">
              <Post />
            </Route>
          </Switch>
      </div>
    </Router>
  );
}

export default App;

As you can see in the code above we created a list of navigation links. The links corresponds to different React components. When we switch to a different link that component is mounted. The Home component is rendered in the root url and Post component will render in the /posts/new link.  We haven’t created the post component yet so let’s create that component.

如您在上面的代码中看到的,我们创建了导航链接列表。 这些链接对应于不同的React组件。 当我们切换到其他链接时,将安装该组件。 Home组件将在根url中呈现,而Post组件将在/posts/new链接中呈现。 我们尚未创建post组件,因此让我们创建该组件。

import React from 'react';

function Post() {
    const [title, setTile] = React.useState();
    const [content, setContent] = React.useState();

    const handleSubmit = event => {
        event.preventDefault();
    }

    return (
      <div>
        <form onSubmit={handleSubmit}>
            <div>
            <label>
                Title:
                <input type="text" value={title} onChange={
                    (e) => setTile(e.target.value)
                } />
            </label>
            </div>
            <div>
            <label>
                Content:
                <textarea type="text" value={content} onChange={
                    (e) => setContent(e.target.value)
                } />
            </label>
            </div>
            <input type="submit" value="Submit" />
        </form>
      </div>
    );
}

export default Post;

This is a very basic React component where we have a form and we have two hooks that are changing the state of the component based on user input. When user submits the form we call the handleSubmit function. We will make our API call in this function. So let’s implement that.

这是一个非常基本的React组件,在其中我们有一个表单,并且有两个挂钩可以根据用户输入更改组件的状态。 当用户提交表单时,我们调用handleSubmit函数。 我们将在此函数中进行API调用。 因此,让我们实现它。

If we navigate to the src/graphql/mutations.js we will see that amplify has already generated some code for us. In this file we have a function called createPost. We have to import this function in our component and execute the mutation. Here’s the code to do that:

如果我们导航到src/graphql/mutations.js我们将看到amplify已经为我们生成了一些代码。 在此文件中,我们有一个名为createPost的函数。 我们必须将此函数导入我们的组件中并执行突变。 这是执行此操作的代码:

import React from 'react';
import { API, graphqlOperation } from 'aws-amplify';
import { createPost } from '../graphql/mutations';

function Post() {
    const [title, setTitle] = React.useState();
    const [content, setContent] = React.useState();

    const handleSubmit = async event => {
        event.preventDefault();
        try {
             let input = {
               title,
               content
            }
             let newPost = await API.graphql(graphqlOperation(createPost, {input}));
             setTitle('');
             setContent('');
             console.log('new post created ->>', newPost)
            }catch (error) {
            console.log(error)
        }
    }

    return (
      <div>
        <form onSubmit={handleSubmit}>
            <div>
            <label>
                Title:
                <input type="text" value={title} onChange={
                    (e) => setTitle(e.target.value)
                } />
            </label>
            </div>
            <div>
            <label>
                Content:
                <textarea type="text" value={content} onChange={
                    (e) => setContent(e.target.value)
                } />
            </label>
            </div>
            <input type="submit" value="Submit" />
        </form>
      </div>
    );
}

export default Post;

You can login to AWS console in the browser and navigate to AppSync and select our application. Select Queries from the menu.

您可以在浏览器中登录到AWS控制台,然后导航到AppSync并选择我们的应用程序。 从菜单中选择查询。

From here click on docs and you will be able to see a detailed docs about all the queries and mutations for our app. We can also verify what parameters are needed for a generated mutation function.

从这里单击文档,您将能够看到有关我们应用程序所有查询和变异的详细文档。 我们还可以验证生成的突变函数需要哪些参数。

列出所有帖子 (Listing all Posts)

Let’s list all the posts in our home page now. If we go look at the src/graphql/queries.js file we will see a listPosts query function.  We can call this function to list all the posts. Let’s call this function in our Home component on component mount. This function will return all the posts from database and we will be rendering them in our home page.

现在让我们列出主页中的所有帖子。 如果我们去看看src/graphql/queries.js文件,我们将看到一个listPosts查询函数。 我们可以调用此函数列出所有帖子。 让我们在组件安装的Home组件中调用此函数。 此函数将从数据库返回所有帖子,我们将在我们的主页中呈现它们。

// Home.js

import React from 'react';
import { withAuthenticator } from 'aws-amplify-react';
import { API, graphqlOperation } from 'aws-amplify';
import { listPosts } from '../graphql/queries';

function Home() {
  const [posts, setPosts] = React.useState([])
  React.useEffect(() => {
    getPosts();
  }, []);

  const getPosts = async () => {
    try {
      let resp = await API.graphql(graphqlOperation(listPosts));
      console.log('===>>>>',resp);
      setPosts(resp.data.listPosts.items)
    } catch (error) {
      console.log('Something went wrong', error);
    }
  }

  return (
    <div >
      <ul>
          {posts.map(p => (
              <li>
                  <h4><a href="">{p.title}</a></h4>
                  <span>By {p.owner}</span>
                  <div>
                    <button>delete</button>
                    <button>Edit</button>
                  </div>
              </li>
          ))}
      </ul>
    </div>
  );
}

export default withAuthenticator(Home);

The code up to this point can be found at the following link:

到目前为止的代码可以在以下链接中找到:

https://github.com/Shadid12/serverless-blog/tree/03-create-read-update-delete

https ://github.com/Shadid12/serverless-blog/tree/03-create-read-update-delete

删除帖子 (Deleting a Post)

Let’s implement the ability to delete a post now. We are already rendering a delete button for each post. Now we will attach an action when the button is pressed.

让我们实现现在删除帖子的功能。 我们已经为每个帖子渲染了一个删除按钮。 现在,我们将在按下按钮时附加一个动作。

As you can guess there is a GraphQL mutation for deleting a post. All we have to do is call this mutation. Here’s the code implementation

可以猜到,有一个GraphQL突变可删除帖子。 我们所要做的就是将此突变称为。 这是代码实现

import React from 'react';
import { withAuthenticator } from 'aws-amplify-react';
import { API, graphqlOperation } from 'aws-amplify';
import { listPosts } from '../graphql/queries';
import { deletePost } from '../graphql/mutations';
import {
  Link
} from "react-router-dom";

function Home() {
  const [posts, setPosts] = React.useState([])
  React.useEffect(() => {
    getPosts();
  }, []);

  const getPosts = async () => {
    try {
      let resp = await API.graphql(graphqlOperation(listPosts));
      console.log('===>>>>',resp);
      setPosts(resp.data.listPosts.items)
    } catch (error) {
      console.log('Something went wrong', error);
    }
  }

  const deleteSelected = async id => {
    try {
      let input = {
        id
      }
      let deleted  = await API.graphql(graphqlOperation(deletePost, {input}));
      let newPosts = posts.filter(p => p.id !== id);
      setPosts(newPosts);
      console.log('Post delete', deleted);
    } catch (error) {
      alert('Not Allowed', error);
    }
  }


  return (
    <div >
      <ul>
          {posts.map(p => (
              <li>
                  <h4><a href="">{p.title}</a></h4>
                  <span>By {p.owner}</span>
                  <div>
                  <button onClick={() => deleteSelected(p.id)}>delete</button>
                  <Link to={`/posts/edit/${p.id}`}>Edit</Link>
                  </div>
              </li>
          ))}
      </ul>
    </div>
  );
}

export default withAuthenticator(Home);

As you can see above we pass in the postId as a param in the function and call the deletePost mutation.

如上所示,我们将postId作为参数传递给函数,并调用deletePost突变。

更新帖子 (Update a Post)

For each post we have an update button. When a user clicks on this button we should route to an update post route. Let’s create a new route in our App Component.

对于每个帖子,我们都有一个更新按钮。 当用户单击此按钮时,我们应该转到更新后的路线。 让我们在应用程序组件中创建一条新路线。

// App.js

<Switch>
   <Route exact path="/">
      <Home />
   </Route>
   <Route path="/posts/new">
      <Post />
   </Route>
   <Route path="/posts/edit/:id">
      <EditPost />
   </Route>
</Switch>

We will create a new component called EditPost. This component will get the id of a post from the url and query that post in the database. After it retrieves a post it will let the user update its content. Once a user updates the input and hits the submit button it will make an update call to our API. Let’s implement this EditPost component.

我们将创建一个名为EditPost的新组件。 该组件将从URL获取帖子的id ,并在数据库中查询该帖子。 在检索帖子后,它将允许用户更新其内容。 用户更新输入并单击“提交”按钮后,它将对我们的API进行更新调用。 让我们实现这个EditPost组件。

import React from 'react';
import { API, graphqlOperation } from 'aws-amplify';
import { updatePost } from '../graphql/mutations';
import { getPost } from '../graphql/queries';
import { useParams } from "react-router-dom";

function EditPost() {
    let { id } = useParams();
    const [title, setTitle] = React.useState();
    const [content, setContent] = React.useState();

    React.useEffect(() => {
        queryPostById();
    }, [])

    const queryPostById = async () => {
        const resp = await API.graphql(graphqlOperation(getPost, { id }));
        console.log('--->>>>', resp)
        setTitle(resp.data.getPost.title);
        setContent(resp.data.getPost.content);
    }

    const handleSubmit = async event => {
        event.preventDefault();
        try {
            let input = {
                id,
                title,
                content
            }
            let newPost = await API.graphql(graphqlOperation(updatePost, {input}));
            setTitle('');
            setContent('');
            console.log('Post Updated ->>', newPost)
          } catch (error) {
            console.log(error)
        }
    }

    return (
      <div>
        <form onSubmit={handleSubmit}>
            <div>
            <label>
                Title:
                <input type="text" value={title} onChange={
                    (e) => setTitle(e.target.value)
                } />
            </label>
            </div>
            <div>
            <label>
                Content:
                <textarea type="text" value={content} onChange={
                    (e) => setContent(e.target.value)
                } />
            </label>
            </div>
            <input type="submit" value="Submit" />
        </form>
      </div>
    );
}

export default EditPost;

This component is very similar to our post component. The only main difference is that on component load we fetch a post and populate the input with the post information. A user can update the content and title. When a user submits the form we call the update mutation from graphql.

此组件与我们的post组件非常相似。 唯一的主要区别是,在组件加载时,我们获取帖子,并使用帖子信息填充输入。 用户可以更新内容和标题。 当用户提交表单时,我们将其称为graphql的更新突变。

We have to change one last thing in our Home component. We have to add in change the edit link so that it routes to the proper post.

我们必须在Home组件中更改最后一件事。 我们必须添加更改编辑链接,以便将其路由到正确的帖子。

return (
    <div >
      <ul>
          {posts.map(p => (
              <li>
                  <h4><a href="">{p.title}</a></h4>
                  <span>By {p.owner}</span>
                  <div>
                  <button onClick={() => deleteSelected(p.id)}>delete</button>
                  <Link to={`/posts/edit/${p.id}`}>Edit</Link>
                  </div>
              </li>
          ))}
      </ul>
    </div>
  )

Perfect, we are done with the update functionality.

完美,我们已经完成了更新功能。

You can find the source code up to this point in the following repository:

您可以在以下存储库中找到到目前为止的源代码:

https://github.com/Shadid12/serverless-blog/tree/04-delete-view

https ://github.com/Shadid12/serverless-blog/tree/04-delete-view

查看帖子 (Viewing a Post)

Let’s see how we can get a detailed view of a particular post. When a user clicks on the post it should route to a detailed view where the user can see the post title, detail and comments associated with that post.

让我们看看如何获​​得特定帖子的详细视图。 当用户单击帖子时,它应该转到详细视图,在该视图中,用户可以查看与该帖子相关的帖子标题,详细信息和评论。

This functionality is very similar to the update functionality. Let’s start with creating a new route in the App component.

此功能与更新功能非常相似。 让我们从在App组件中创建新路线开始。

<Route path="/posts/:id">
    <ViewPost />
</Route>

Now let’s create the ViewPost component.

现在让我们创建ViewPost组件。

import React from 'react';
import { API, graphqlOperation } from 'aws-amplify';
import { getPost } from '../graphql/queries';
import { useParams } from "react-router-dom";

function ViewPost() {
    let { id } = useParams();
    const [post, setPost] = React.useState();

    React.useEffect(() => {
        queryPostById();
    }, [])

    const queryPostById = async () => {
        const resp = await API.graphql(graphqlOperation(getPost, { id }));
        console.log('--->>>>', resp)
        setPost(resp.data.getPost);
    }

    if(!post) {
        return <div>Loading....</div>
    }
    return (
      <div>
        <h1>{post.title}</h1>
        <div>
            <span>By <b>{post.owner}</b></span>
        </div>
        <p>{post.content}</p>
        <ul>
            {
                post.comments.items.map(com => (<li>{com.content}</li>))
            }
        </ul>
      </div>
    );
}

export default ViewPost;

As you can see above code, the view post component is querying the post by id from database and then it is displaying the content of the post.

如您在上面的代码中看到的,视图帖子组件正在按ID从数据库中查询帖子,然后显示帖子的内容。

Now in our home component we need to change the url like below:

现在在我们的home组件中,我们需要更改网址,如下所示:

return (
    <div >
      <ul>
          {posts.map(p => (
              <li>
                  <h4><Link to={`/posts/${p.id}`}>{p.title}</Link></h4>
                  <span>By {p.owner}</span>
                  <div>
                  <button onClick={() => deleteSelected(p.id)}>delete</button>
                  <Link to={`/posts/edit/${p.id}`}>Edit</Link>
                  </div>
              </li>
          ))}
      </ul>
    </div>
  );

And that’s it. We have implemented create, read and update and delete functionality. As an exercise you can try to add comments to each posts.

就是这样。 我们已经实现了创建,读取,更新和删除功能。 作为练习,您可以尝试在每个帖子中添加评论。

I hope the topics discussed in this article were helpful. The basic concepts we discussed should be enough to get you started with your own full stack serverless applications.

我希望本文讨论的主题对您有所帮助。 我们讨论的基本概念应该足以使您开始使用自己的全栈无服务器应用程序。

If you have any questions feel free to get in touch with me. Until next time 

如果您有任何疑问,请随时与我联系。 直到下次time

翻译自: https://www.freecodecamp.org/news/how-to-build-a-full-stack-serverless-application-with-react-and-amplify/

react全栈

 类似资料: