简体   繁体   English

阿波罗(Apollo)中的自动UI更新问题:`updateQuery`与`subscribeToMore`无法正常工作

[英]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 : 我订阅了allMessagesQuerycomponentDidMount

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. 收到订阅后, allMessagesthis.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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM