GraphQL Apollo客户端的订阅组件

时间:2018-08-10 22:01:00

标签: graphql apollo apollo-client subscriptions graphql-subscriptions

我有一个已经使用 subscribeToMore

进行订阅的应用程序

查询组件

<Query query={GET_MESSAGES}>
  {({ data, subscribeToMore }) => {
    return (
      <MessageList
        messages={data.allMessages}
        subscribeToMore={subscribeToMore}/>
    );
  }}
</Query>

该查询会加载一条消息列表,据我所知,我们将订户附加到ComponentDidMount上,因此,每当我在查询中的列表中添加新元素时,我的订阅都会侦听该订阅并执行我想要的任何操作(在这种情况下,请将新邮件添加到我当前的邮件列表中。

邮件列表组件:

export default class MessageList extends React.Component {
componentDidMount() {
  this.props.subscribeToMore({
    document: MESSAGE_CREATED,
    updateQuery: (prev, { subscriptionData }) => {
      if (!subscriptionData.data) return prev;
      return {
        allMessages: [
          subscriptionData.data.messageCreated,
          ...prev.allMessages
        ],
      };
    },
  });
}

render() {
  return (
    <div>
      {this.props.messages.map(message => (
        <MessageElement key={message.id} 
                        message={message}/>
      ))}
    </div>
  );
}}

我想添加另一个订阅,因此,如果我编辑邮件,信息将实时更新。为了实现这一点,我使用 Subscription

创建了以下组件

消息组件(我想根据更新的消息在其中添加另一个订阅)

export default class MessageElement extends Component{

componentDidMount() {
    this.messageUpdatedSubscription();
}


messageUpdatedSubscription = () => (
    <Subscription
      subscription={MESSAGE_UPDATED}>
      {({ data: { messageUpdated } }) => (
        console.log('Do smthg???',messageUpdated)
      )}
    </Subscription>
  );


render(){
    return(
        <Mutation mutation={UPDATE_MESSAGE} key={this.props.message.id}>
         {updateMessage => (
            <div>
                <div>{this.props.message.text}</div> 
                <div>
                    <Star active={this.props.message.isFavorite} 
                         onClick={() => { updateMessage({ variables: { 
                                          id: this.props.message.id, 
                                          text:this.props.message.text,
                                          isFavorite:!this.props.message.isFavorite } });
                    }}/>
                </div>
            </div>
          )}
       </Mutation>);
}}

我在服务器上的订阅正在运行,因为我已经在查询中对MESSAGE_CREATED的订阅正常工作,并且我已经测试了在服务器上触发了对我的MESSAGE_UPDATED的订阅。但是,我无法弄清楚为什么UI不显示或console.log好像没有监听订阅一样。

我可以通过订阅组件还是通过SubscribeToMore来实现?

预先感谢

2 个答案:

答案 0 :(得分:1)

无法在ComponentDidMount中启动订阅组件。它必须驻留在render()生命周期方法中。它的参数可以在ComponentDidMount中使用,但不能在组件中使用。

我可以想到3种可能的解决方案:

1)您可以尝试将Subscription方法放入渲染方法中。您只需将其嵌套在Mutation组件的内部或外部即可。

2)您可以在该组件的父级中启动订阅组件,并将其参数(messageUpdate)向下传递给组件MessageElement。然后,您可以在ComponentDidMount中使用messageUpdate道具。

3)您可以使用Apollo的高阶组件。然后,您可以在道具中访问messageUpdate。 (免责声明-我之前没有尝试过)。

我希望这会有所帮助!

答案 1 :(得分:1)

基于@cory-mcaboy的建议,我将我的订阅嵌套在突变中。 我还发现,由于我有一条消息列表,我只是想根据我正在更新的消息而不是整个列表触发订阅。我必须通过以下方式在后端和前端上修改订阅:

服务器架构

const typeDefs = gql` type Subscription {
                      messageUpdated(id: Int!): Message}`;

服务器解析器

 Subscription: {
    messageUpdated: {
        subscribe: withFilter(
                   () => pubsub.asyncIterator([MESSAGE_UPDATED]),
                         (payload, variables) => {
                         return payload.messageUpdated.id === variables.id;
                                        },
                   ),
      },
}

客户端组件

const MESSAGE_UPDATED = gql` subscription messageUpdated($id: Int!){
            messageUpdated(id:$id)
            { 
                id
                text
                isFavorite
            }}`;

export default class MessageElement extends Component{
render(){
    return(<Mutation mutation={UPDATE_MESSAGE} key={this.props.message.id}>
            {updateMessage => (
                <div>
                    <div>{this.props.message.text}</div> 
                     <Subscription subscription={MESSAGE_UPDATED}
                                   variables={{ id: this.props.message.id }}>
                        {() => {
                            return <Star active={this.props.message.isFavorite} 
                                        onClick={() => { updateMessage({ variables: { 
                                                                        id: this.props.message.id, 
                                                                        text: this.props.message.text,
                                                                        isFavorite: !this.props.message.isFavorite } });}}/>
                        }}
                    </Subscription>
                </div>
            )}
        </Mutation>
    );
}}

您可以在以下存储库中查看代码:后端itr-apollo-server,前端itr-apollo-client