[英]Issue with automatic UI updates in Apollo: `updateQuery` not working properly with `subscribeToMore`
我正在為聊天應用程序使用GraphQL訂閱 ,但是UI更新存在問題。
這是我正在使用的查詢和變異:
const createMessage = gql`
mutation createMessage($text: String!, $sentById: ID!) {
createMessage(text: $text, sentById: $sentById) {
id
text
}
}
`
const allMessages = gql`
query allMessages {
allMessages {
id
text
createdAt
sentBy {
name
location {
latitude
longitude
}
}
}
}
`
然后,在導出時,我將包裝Chat
組件,如下所示:
export default graphql(createMessage, {name : 'createMessageMutation'})(
graphql(allMessages, {name: 'allMessagesQuery'})(Chat)
)
我訂閱了allMessagesQuery
在componentDidMount
:
componentDidMount() {
// Subscribe to `CREATED`-mutations
this.createMessageSubscription = this.props.allMessagesQuery.subscribeToMore({
document: gql`
subscription {
Message(filter: {
mutation_in: [CREATED]
}) {
node {
id
text
createdAt
sentBy {
name
}
}
}
}
`,
updateQuery: (previousState, {subscriptionData}) => {
console.log('Chat - received subscription: ', previousState, subscriptionData)
const newMessage = subscriptionData.data.Message.node
const messages = previousState.allMessages.concat([newMessage])
console.log('Chat - new messages: ', messages.length, messages) // prints the correct array with the new message!!
return {
allMessages: messages
}
},
onError: (err) => console.error(err),
})
}
通過聊天發送消息后,訂閱已成功觸發,並且我看到兩個日志記錄語句也包含預期的數據。 因此, messages
的內容在updateQuery
中絕對正確!
但是,UI不會自動更新,實際上,所有先前顯示的消息都會消失。
我的render
方法如下所示:
render() {
console.log('Chat - render: ', this.props.allMessagesQuery)
return (
<div className='Chat'>
<ChatMessages
messages={this.props.allMessagesQuery.allMessages || []}
/>
<ChatInput
message={this.state.message}
onTextInput={(message) => this.setState({message})}
onResetText={() => this.setState({message: ''})}
onSend={this._onSend}
/>
</div>
)
}
render
中的日志記錄語句顯示,最初, this.props.allMessagesQuery
具有數組allMessages
,因此在初始加載后一切正常。
收到訂閱后, allMessages
從this.props.allMessagesQuery
中消失,這就是為什么將空數組分配給ChatMessages
呈現任何內容的原因。
在觸發訂閱之前 ✅
訂閱觸發后 ❌
我再研究了一次文檔后才發現,這是我的錯誤!
Apollo文檔的這一部分幫助我解決了這個問題:
請記住:您需要確保在需要標准化結果的每個查詢中選擇ID。
因此,將id
字段添加到查詢和訂閱的返回有效負載中實際上有所幫助。
const allMessages = gql`
query allMessages {
allMessages {
id
text
createdAt
sentBy {
id
name
location {
id
latitude
longitude
}
}
}
}
`
subscription {
Message(filter: {
mutation_in: [CREATED]
}) {
node {
id
text
createdAt
sentBy {
id
name
}
}
}
}
在您的更新查詢中,previousState是allMessages查詢,該查詢保存在react apollo存儲中。
要更新商店,您必須進行深拷貝或使用一些幫助程序,例如, 反應不變性幫助程序 。 阿波羅開發人員頁面提供了一些有關如何正確更新商店的信息Query 。
在您的情況下,它可能看起來像這樣
... updateQuery: (previousState, { subscriptionData }) => { const newMessage = subscriptionData.data.Message.node; return update(previousState, { allMessages: { $push: [newMessage] }, }); } ...
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.