简易版 AWS Amplify + React + GraphQL 应用
这是一份关于如何使用 GraphQL 和 AWS Amplify 搭建一个非常基础的 React 应用的简单指南。遗憾的是,AWS 的文档并不完善,我经常会忘记具体步骤,也无法每次都完全按照他们的示例操作。
我认为最大的问题在于文档中关于如何为应用添加身份验证的部分。如果你不需要身份验证,你可能会想跳过这部分,但不幸的是,其中一个最关键的步骤只在那里有详细说明,而不是作为所有想要使用 Amplify 的应用都必须遵循的基本预备步骤。
不仅如此,我能找到的所有教程和示例都极其复杂,其中包含的库和代码设计策略更是让我困惑不已,偏离了方向。所以我在这里提供一个我梦寐以求的极简示例。
最后,create-react-app 默认会创建一个函数式组件,而文档示例却使用了经典组件,这同样令人困惑。所以,下面是正文:
要求:(
截至2019年11月中旬发布此帖时)
- 节点 13.1.0
- amplify 3.16.0
- create-react-app 3.2.0
本文假设您已经运行过相关程序aws configure——就我个人而言,文档的这部分内容从未出现过问题。
步骤:
$ create-react-app my-project-name
$ cd my-project-name
$ yarn add aws-amplify aws-amplify-react
$ amplify init
# follow the default instructions
# wait for the cloud processes to finish
$ amplify add api
# follow prompts for GraphQL +
# API Key for authorization +
# default prompts that will guide you
# in creating a schema +
# Single-Object +
# No to editing the schema
# You now have a basic API for a simple ToDo model
$ amplify push
# say Yes to generate the code for your GraphQL API
# (all the default answers will work fine for this post)
# ... and wait a while (-:
现在,这里是他们隐藏在文档“添加身份验证”部分的关键代码,供我们这些不需要添加身份验证的人参考:
将此代码添加到index.js
// other imports...
import Amplify from "aws-amplify"
import awsconfig from "./aws-exports"
Amplify.configure(awsconfig)
// ReactDOM.render...
接下来,从最基本的开始App.js
import React from 'react';
import './App.css';
function App() {
return (
<div className="App">
</div>
);
}
export default App;
为了避免以后 CSS 出现问题,请考虑替换.App以下定义App.css:
.App {
padding: 1rem;
/* instead of text-align: center; */
}
现在让我们添加一个基本输入来创建待办事项并将其存储在 AWS AppSync GraphQL 后端。
首先,我们需要添加一个受控输入,在函数式组件中,我们必须导入useState
// change FROM this:
import React from 'react';
// TO this:
import React, { useState } from 'react';
在应用程序功能的顶部,添加以下内容:
function App() {
const [todoName, setTodoName] = useState('')
// ...the rest...
}
返回输入框“+”按钮的JSX代码:
// ...
return (
<div className="App">
<input type="text" value={todoName} onChange={handleChange} />
<button onClick={addTodo}>Add ToDo</button>
</div>
);
//...
以及用于处理受控输入变化的函数:
// ...
const handleChange = (evt) => {
setTodoName(evt.target.value)
}
// return ( ...
现在,为了启用该addTodo功能,我们将导入 API 和 GraphQL 工具:
import { API, graphqlOperation } from "aws-amplify"
import { createTodo } from "./graphql/mutations
最后是addTodo函数
// ...
const addTodo = async () => {
await API.graphql(
graphqlOperation(createTodo, { input: { name: todoName } })
)
setTodoName('') // make the input blank again
}
// Another fun fact of the AWS docs is
// they don't give the updated
// example that the 2nd argument
// is an object with the "input" property (-:
// ...
通过启动本地服务器后,yarn start您现在应该能够在 AWS GraphQL 后端成功创建待办事项了!
为了确保万无一失,我们还是把待办事项列出来吧。
注意:以下可能是一个非常简单的实现方式,其他人可能会提出“更好”的方法,但我只是想确保我的应用程序在原型设计阶段能够正常工作。
我们将导入 GraphQL 查询:
import { listTodos } from "./graphql/queries"
然后添加另一个 useState 来获取待办事项数组:
const [todoItems, setTodoItems] = useState([])
创建一个函数,用于从 AWS 获取待办事项:
const updateTodos = async () => {
const allTodos = await API.graphql(graphqlOperation(listTodos))
setTodoItems(allTodos.data.listTodos.items)
}
添加一些简单的 JSX 代码来列出我们的待办事项:
// ...
return (
// ...
<ul>
{todoItems.map((item) => {
return <li key={item.id}>{ item.name }</li>
})}
</ul>
)
修改我们的 addTodo 函数:
(是的,使用 GraphQL 订阅有更好的方法,但目前这样就可以了!)
const addTodo = async () => {
await API.graphql(
graphqlOperation(createTodo, { input: { name: todoName } })
)
setTodoName('')
updateTodos() // here it is
}
updateTodos以及在返回 JSX 之前进行的非常非常天真的调用:
// ...
updateTodos()
return ( //...
//...
)
}
好了,应该就是这样了!
以下是完整内容。index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import Amplify from "aws-amplify"
import awsconfig from "./aws-exports"
Amplify.configure(awsconfig)
ReactDOM.render(<App />, document.getElementById('root'));
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();
满App.js
import React, { useState } from 'react';
import './App.css';
import { API, graphqlOperation } from "aws-amplify"
import { createTodo } from "./graphql/mutations"
import { listTodos } from "./graphql/queries"
function App() {
const [todoName, setTodoName] = useState('')
const [todoItems, setTodoItems] = useState([])
const addTodo = async () => {
await API.graphql(
graphqlOperation(createTodo, { input: { name: todoName } })
)
setTodoName('')
updateTodos()
}
const handleChange = (evt) => {
setTodoName(evt.target.value)
}
const updateTodos = async () => {
const allTodos = await API.graphql(graphqlOperation(listTodos))
setTodoItems(allTodos.data.listTodos.items)
}
updateTodos()
return (
<div className="App">
<input type="text" value={todoName} onChange={handleChange} />
<button onClick={addTodo}>Add ToDo</button>
<ul>
{todoItems.map((item) => {
return <li key={item.id}>{ item.name }</li>
})}
</ul>
</div>
);
}
export default App;