0

我正在为我的聊天应用程序使用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)
)

我订阅了allMessagesQueryin 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而没有渲染任何内容的原因。

订阅触发前✅</p>

在此处输入图像描述

订阅触发后❌</p>

在此处输入图像描述

4

2 回答 2

0

我在再次挖掘文档后发现了这一点,这是我的错误!

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
            }
        }
    }
}
于 2017-02-28T09:02:15.263 回答
-1

在您的更新查询中,previousState 是保存在反应阿波罗存储中的 allMessages 查询。

要更新商店,您必须进行深层复制或使用一些帮助器,例如反应不变性帮助器。apollo 开发者页面提供了一些关于如何正确更新商店update Query的信息。

在你的情况下,它可能看起来像这样

...
updateQuery: (previousState, { subscriptionData }) => {
  const newMessage = subscriptionData.data.Message.node;
  return update(previousState, {
    allMessages: { $push: [newMessage] },
  });
}
...

于 2017-02-28T07:01:13.423 回答