AWS Amplify in React,如何从订阅的侦听器呈现新数据
Posted
技术标签:
【中文标题】AWS Amplify in React,如何从订阅的侦听器呈现新数据【英文标题】:AWS Amplify in React, how can I render the new data from the subscribed listener 【发布时间】:2021-07-06 09:27:14 【问题描述】:我正在开发一个 React 项目并使用 AWS Amplify 作为无服务器后端的工具,其中我有一个 DynamoDB 作为我在 AWS 云中的数据库。
我的 React 应用需要检测 DynamoDB 中的实时数据更新。我正在使用 Amplify 的 GraphQL API。
Amplify 生成的 GraphQL API 提供了一个subscriptions
API,用于实时订阅数据更改。我认为这正是我需要的,所以我正在使用它:
import React, useEffect, useState, useRef from 'react';
import Amplify, API, graphqlOperation from 'aws-amplify';
import onCreateData from './graphql/subscriptions';
// subscribe to listen to new data creation in DynamoDB
const subscription = API.graphql(
graphqlOperation(onCreateData)
).subscribe(
next: (newData) =>
// New data is received here outside 'App' functional component,
// how can I render the data then?
console.log(`new data: $JSON.stringify(newData)`);
);
// I can't put the above subscription code inside App component, I don't know why but it just doesn't work unless I move it outside the App functional component.
function App()
const [dataArray, setDataArray] = useState([]);
...
useEffect(() =>
fetchDataArray();
showDataArray();
return () =>
//cleanup
, [dataArra])
return (<div>
<canvas ref=canvasRef/>
</div>)
export default App;
问题是 subscription
用于 DynamoDB 中的新数据插入仅在我将其放在 function App()...
之外时才有效,如上所示。那么,当订阅回调next: (newData)
收到newData
时,如何在App
组件中显示新数据?
你可以在我的App
组件中看到我有状态变量dataArray
,理想的解决方案是用newData
更新这个dataArray
状态,但我认为现在不可能。所以,总的来说,我想知道现在如何在我的App
组件中显示新数据?
附: Amplify GraphQL API doc sample code(如果您看到“订阅”部分)也显示订阅代码与导入处于同一级别。
【问题讨论】:
学习一些教程? react FC(你的App是FC,可以转成类组件)需要像useSubscription
-apollographql.com/docs/react/data/subscriptions这样的hook形式
我想知道如何订阅我的功能组件,而不是类组件。有没有可能。
您是否尝试在 App 中使用 useEffect 挂钩添加它?
【参考方案1】:
我们在我们的项目中使用 amplify,我们的一个示例是下面的简单聊天功能:
interface ChatMessagesProps
internal?: boolean
convoId: string
export const ChatMessages: FC<ChatMessagesProps> = ( internal, convoId ) =>
const classes = useStyles()
const
appState: user
= useAppState()
let [messages, setMessages] = useState<any>([])
let [currentConversationId, setConversationId] = useState<string>(convoId)
const listRef = useRef<VariableSizeProps>()
let subscription = useRef<ISubscriptionObject | null>(null)
let updateSubscription = useRef<ISubscriptionObject | null>(null)
const addNewMessage = ( onCreateMessage ) =>
console.log(onCreateMessage)
// from here we can do whatever we want with the data within the context of this component
const messageUpdated = ( onUpdateMessage ) =>
console.log(onUpdateMessage)
// from here we can do whatever we want with the data within the context of this component
const getConversationDetails = async () =>
subscription.current = graphQLSubscription(
onCreateMessage,
conversationId: currentConversationId ,
addNewMessage
)
updateSubscription.current = graphQLSubscription(
onUpdateMessage,
conversationId: currentConversationId ,
messageUpdated
)
useEffect(() =>
if (currentConversationId)
getConversationDetails()
return () =>
subscription?.current?.unsubscribe()
updateSubscription?.current?.unsubscribe()
, [currentConversationId])
return (
<div className=classes.root>
<MessageList listRef=listRef messages=messages internal=internal />
<MessageInput userId=user?.id || '' internal=internal conversationId=currentConversationId />
</div>
)
const useStyles = makeStyles(() => (
root:
width: '100%',
height: '100%',
backgroundColor: 'white',
position: 'relative'
))
我们使用助手graphQLSubscription
export const graphQLSubscription = (subscription: string, options: any, callback: (d: any) => void) =>
return API.graphql(graphqlOperation(subscription, options)).subscribe(
next: ( value: data, errors ) =>
console.log(errors)
callback(data)
)
对于您的示例代码,您只想将订阅存储在 ref 中,以便能够在卸载时取消订阅
import React, useEffect, useState, useRef from 'react';
import Amplify, API, graphqlOperation from 'aws-amplify';
import onCreateData from './graphql/subscriptions';
function App()
const [dataArray, setDataArray] = useState([]);
const subscriptionRef = useRef()
...
useEffect(() =>
fetchDataArray();
showDataArray();
subscriptionRef.current = API.graphql(
graphqlOperation(onCreateData)
).subscribe(
next: (newData) =>
// New data is received here outside 'App' functional component,
// how can I render the data then?
console.log(`new data: $JSON.stringify(newData)`);
);
return () =>
//cleanup
subscriptionRef.current.unsubscribe()
, [dataArra])
return (<div>
<canvas ref=canvasRef/>
</div>)
export default App;
您可以从那里将其提取到组件内或您的项目中的辅助函数中
【讨论】:
以上是关于AWS Amplify in React,如何从订阅的侦听器呈现新数据的主要内容,如果未能解决你的问题,请参考以下文章
aws-amplify-react 和 @aws-amplify/ui-react 有啥区别?
如何在带有 Typescript 项目的 React Native 中使用 AWS Amplify?
如何使用 aws amplify 保持用户登录 react-native
AWS Amplify Authenticator 和 React Native Navigation Container 如何在两者之间切换