[英]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.