[英]Issue with automatic UI updates in Apollo: `updateQuery` not working properly with `subscribeToMore`
I'm using GraphQL subscriptions for my chat application, but I have an issue with the UI updates. 我正在为聊天应用程序使用GraphQL订阅 ,但是UI更新存在问题。
Here are the query and the mutation I'm using: 这是我正在使用的查询和变异:
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
}
}
}
}
`
Then, when exporting, I'm wrapping my Chat
component like so: 然后,在导出时,我将包装
Chat
组件,如下所示:
export default graphql(createMessage, {name : 'createMessageMutation'})(
graphql(allMessages, {name: 'allMessagesQuery'})(Chat)
)
I'm subscribing to the allMessagesQuery
in componentDidMount
: 我订阅了
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),
})
}
After I sent the message through the chat, the subscription is triggered successfully and I see the two logging statements that also contain the expected data. 通过聊天发送消息后,订阅已成功触发,并且我看到两个日志记录语句也包含预期的数据。 So the contents of
messages
are definitely correct within updateQuery
! 因此,
messages
的内容在updateQuery
中绝对正确!
However, the UI doesn't update automatically, in fact, all the previously displayed messages disappear. 但是,UI不会自动更新,实际上,所有先前显示的消息都会消失。
My render
method looks as follows: 我的
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>
)
}
The logging statement in render
shows that initially, this.props.allMessagesQuery
has the array allMessages
, so everything works after the initial loading. render
中的日志记录语句显示,最初, this.props.allMessagesQuery
具有数组allMessages
,因此在初始加载后一切正常。
After the subscription is received, allMessages
disappears from this.props.allMessagesQuery
which is why an empty array is given to ChatMessages
and nothing is rendered. 收到订阅后,
allMessages
从this.props.allMessagesQuery
中消失,这就是为什么将空数组分配给ChatMessages
呈现任何内容的原因。
Before subscription is triggered ✅ 在触发订阅之前 ✅
After subscription is triggered ❌ 订阅触发后 ❌
I figured it out after digging through the docs one more time, it was a mistake on my end! 我再研究了一次文档后才发现,这是我的错误!
This part from the Apollo docs helped me solve the issue: Apollo文档的这一部分帮助我解决了这个问题:
Remember: You'll need to ensure that you select IDs in every query where you need the results to be normalized.
请记住:您需要确保在需要标准化结果的每个查询中选择ID。
So, adding the id
fields to the returned payload of my queries and subscriptions actually helped. 因此,将
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
}
}
}
}
In your update Query the previousState is the allMessages query that is saved in the react apollo store. 在您的更新查询中,previousState是allMessages查询,该查询保存在react apollo存储中。
To update the store you have to make a deep copy or use some helper eg reacts immutability helper . 要更新商店,您必须进行深拷贝或使用一些帮助程序,例如, 反应不变性帮助程序 。 The apollo developers page gives some information about how to update the store correctly update Query .
阿波罗开发人员页面提供了一些有关如何正确更新商店的信息Query 。
In your case it could look like this 在您的情况下,它可能看起来像这样
... updateQuery: (previousState, { subscriptionData }) => { const newMessage = subscriptionData.data.Message.node; return update(previousState, { allMessages: { $push: [newMessage] }, }); } ...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.