1

我有一个订阅的应用程序已经在使用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>);
}}

我在服务器上的订阅正在工作,因为我已经在 Query 上订阅了 MESSAGE_CREATED,并且我已经在服务器上测试了我对 MESSAGE_UPDATED 的订阅已被触发。但是,我无法弄清楚为什么 UI 没有显示或 console.log 任何内容,就好像它没有收听订阅一样。

我可以通过订阅组件或 subscribeToMore 来实现这一点吗?

提前致谢

4

2 回答 2

1

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

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

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

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

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

我希望这有帮助!

于 2018-08-13T13:52:41.963 回答
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>
    );
}}

您可以在以下 repo 中看到代码:后端itr-apollo-server,前端itr-apollo-client

于 2018-08-13T16:26:58.943 回答