Apollo 中的自动 UI 更新问题:`updateQuery` 不能与 `subscribeToMore` 一起正常工作 [英] Issue with automatic UI updates in Apollo: `updateQuery` not working properly with `subscribeToMore`

查看:24
本文介绍了Apollo 中的自动 UI 更新问题:`updateQuery` 不能与 `subscribeToMore` 一起正常工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我为我的聊天应用程序使用 GraphQL 订阅,但 UI 更新出现问题.

这是我使用的查询和变更:

const createMessage = gql`突变 createMessage($text: String!, $sentById: ID!) {createMessage(文本:$text,sentById:$sentById){ID文本}}`const allMessages = gql`查询所有消息 {所有消息{ID文本创建于由..送出 {姓名地点 {纬度经度}}}}`

然后,在导出时,我像这样包装我的 Chat 组件:

导出默认 graphql(createMessage, {name : 'createMessageMutation'})(graphql(allMessages, {name: 'allMessagesQuery'})(Chat))

我订阅了 componentDidMount 中的 allMessagesQuery:

componentDidMount() {//订阅`CREATED`-mutationsthis.createMessageSubscription = this.props.allMessagesQuery.subscribeToMore({文档:gql`订阅{消息(过滤器:{突变输入:[创建]}) {节点{ID文本创建于由..送出 {姓名}}}}`,updateQuery: (previousState, {subscriptionData}) =>{console.log('Chat - 收到订阅:', previousState, subscriptionData)const newMessage = subscriptionData.data.Message.nodeconst 消息 = previousState.allMessages.concat([newMessage])console.log('Chat - new messages: ', messages.length, messages)//用新消息打印正确的数组!!返回 {allMessages:消息}},onError: (err) =>控制台错误(错误),})}

我通过聊天发送消息后,订阅触发成功,我看到两个日志语句也包含预期数据.所以messages的内容在updateQuery中肯定是正确的!

但是,UI 不会自动更新,实际上,之前显示的所有消息都会消失.

我的 render 方法如下所示:

render() {console.log('聊天 - 渲染:', this.props.allMessagesQuery)返回 (

<聊天消息消息={this.props.allMessagesQuery.allMessages ||[]}/><聊天输入消息={this.state.message}onTextInput={(message) =>this.setState({message})}onResetText={() =>this.setState({消息:''})}onSend={this._onSend}/>

)}

render 中的日志语句显示,最初,this.props.allMessagesQuery 有数组 allMessages,所以在初始加载后一切正常.

收到订阅后,allMessagesthis.props.allMessagesQuery中消失,这就是为什么给一个空数组的原因ChatMessages 并没有呈现任何内容.

订阅触发前

订阅触发后

解决方案

我又翻了一遍文档才明白,这是我的错误!

Apollo docs 中的这部分帮助我解决了这个问题:

<块引用>

请记住:您需要确保在每个需要标准化结果的查询中选择 ID.

因此,将 id 字段添加到我的查询和订阅返回的有效负载实际上有帮助.

const allMessages = gql`查询所有消息 {所有消息{ID文本创建于由..送出 {ID姓名地点 {ID纬度经度}}}}`订阅{消息(过滤器:{突变输入:[创建]}) {节点{ID文本创建于由..送出 {ID姓名}}}}

I'm using GraphQL subscriptions for my chat application, but I have an issue with the UI updates.

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:

export default graphql(createMessage, {name : 'createMessageMutation'})(
  graphql(allMessages, {name: 'allMessagesQuery'})(Chat)
)

I'm subscribing to the allMessagesQuery in 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!

However, the UI doesn't update automatically, in fact, all the previously displayed messages disappear.

My render method looks as follows:

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.

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.

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:

Remember: You'll need to ensure that you select IDs in every query where you need the results to be normalized.

So, adding the id fields to the returned payload of my queries and subscriptions actually helped.

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
            }
        }
    }
}

这篇关于Apollo 中的自动 UI 更新问题:`updateQuery` 不能与 `subscribeToMore` 一起正常工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆