Lee*_*fin 4 amazon-web-services amazon-dynamodb reactjs graphql aws-amplify
我正在开发一个 React 项目并使用 AWS Amplify 作为无服务器后端工具,其中我在 AWS 云中使用 DynamoDB 作为数据库。
我的 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;
Run Code Online (Sandbox Code Playgroud)
问题是,subscription只有当我将新数据插入到 DynamoDB 之外时,DynamoDB 中的新数据插入才有效,function App(){...}正如您在上面看到的那样。那么,当newData订阅回调中收到 时next: (newData),如何在App组件中显示新数据呢?
App您可以在我的组件内部看到我有状态变量dataArray,理想的解决方案是更新此dataArray状态newData,但我认为现在这是不可能的。所以,总的来说,我想知道现在如何在App组件中显示新数据?
PS Amplify GraphQL API 文档示例代码(如果您看到“订阅”部分)还显示订阅代码与导入处于同一级别。
我们在项目中使用 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'
}
}))
Run Code Online (Sandbox Code Playgroud)
我们使用助手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)
}
})
}
Run Code Online (Sandbox Code Playgroud)
对于您的示例代码,您只想将订阅存储在引用中,以便能够在卸载时取消订阅
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;
Run Code Online (Sandbox Code Playgroud)
从那里您可以将其提取到组件内或项目内的辅助函数中,如上面所示
| 归档时间: |
|
| 查看次数: |
1992 次 |
| 最近记录: |