使用Apollo,我如何区分新创建的对象?

时间:2017-02-20 00:46:47

标签: javascript graphql apollo-client

我的用例如下:

我有一个使用GraphQL查询获取的注释列表。当用户编写新注释时,它将使用GraphQL突变进行提交。然后我使用updateQueries将新评论附加到列表中。

在用户界面中,我想突出显示新创建的评论。我尝试在isNew: true的新评论中添加属性mutationResult,但Apollo在将其保存到商店之前删除了该属性(我认为这是因为isNew字段不是&n #39;在gql查询中请求。)

有没有办法实现这个目标?

2 个答案:

答案 0 :(得分:0)

取决于"新创建的对象"的含义。如果是可以登录的用户的基于身份验证的应用程序,则可以将create_date评论与某个last_online用户日期进行比较。如果用户没有被迫创建帐户,您可以将此类信息存储在本地存储或cookie中(当他/她上次访问该网站时)。

另一方面,如果您考虑评论列表的实时更新,我建议您使用websockets查看graphql-subscriptions。它使用pub-sub机制为您的用户界面提供反应性。简单的用例 - 每当向帖子添加新评论时,每个用户/查看者都会收到相关通知,评论可以附加到评论列表中并以您希望的方式突出显示。

为了实现这一目标,您可以创建一个名为subscription的{​​{1}},客户端会订阅,每次创建新评论时,应用程序的newCommentAdded侧会通知(server)。

这种情况的简单实现可能看起来像那样

publish

以上部分仅是const Subscription = new GraphQLObjectType({ name: 'Subscription', fields: { newCommentAdded: { type: Comment, // this would be your GraphQLObject type for Comment resolve: (root, args, context) => { return root.comment; } } } }); // then create graphql schema with use of above defined subscription const graphQLSchema = new GraphQLSchema({ query: Query, // your query object mutation: Mutation, // your mutation object subscription: Subscription }); 部分,但有必要创建一个使用graphql-js机制的SubscriptionManager

PubSub

最后一步是通过上面创建的import { SubscriptionManager, PubSub } from 'graphql-subscriptions'; const pubSub = new PubSub(); const subscriptionManagerOptions = { schema: graphQLSchema, setupFunctions: { newCommentAdded: (options, args) => { newCommentAdded: { filter: ( payload ) => { // return true -> means that the subscrition will be published to the client side in every single case you call the 'publish' method // here you can provide some conditions when to publish the result, like IDs of currently logged in user to whom you would publish the newly created comment return true; } } }, pubsub: pubSub }); const subscriptionManager = new SubscriptionManager(subscriptionManagerOptions); export { subscriptionManager, pubSub }; 实例,在必要时向客户端publish新创建的评论。你可以在变异方法中创建新评论,或者在任何需要的地方

SubscriptionManager

为了使用// here newComment is your comment instance subscriptionManager.publish( 'newCommentAdded', { comment: newComment } ); 来建立pub-sub机制,有必要在主服务器旁边创建这样的服务器。您可以使用subscriptions-transport-ws模块。

这种解决方案的最大优点是它可以为您的应用程序提供反应性(实时更改应用于帖子下方的评论列表等)。我希望这对你的用例来说可能是一个不错的选择。

答案 1 :(得分:0)

我可以看到这样做有两种方式。您是对的,Apollo将删除isNew值,因为它不是您的架构的一部分,并且未在查询选择集中列出。我喜欢分离由apollo管理的服务器数据和前端应用程序状态的问题,这些问题有助于使用redux / flux,甚至更简单地通过在组件的状态下管理它。

Apollo为您提供了自己的redux商店选项。您可以允许apollo管理其数据获取逻辑,然后管理您自己的前端状态。以下是一篇讨论如何执行此操作的文章:http://dev.apollodata.com/react/redux.html

如果您使用的是React,则可以使用组件生命周期挂钩来检测何时出现新注释。这可能是一个黑客,但您可以使用componentWillReceiveProps将新的评论列表与旧的评论列表进行比较,确定哪些是新的,将其存储在组件状态中,然后在一段时间后使它们无效时间使用setTimeout

componentWillReceiveProps(newProps) {

  // Compute a diff.
  const oldCommentIds = new Set(this.props.data.allComments.map(comment => comment.id));
  const nextCommentIds = new Set(newProps.data.allComments.map(comment => comment.id));
  const newCommentIds = new Set(
    [...nextCommentIds].filter(commentId => !oldCommentIds.has(commentId))
  );
  this.setState({
    newCommentIds
  });

  // invalidate after 1 second
  const that = this;
  setTimeout(() => {
    that.setState({
      newCommentIds: new Set()
    })
  }, 1000);
}

// Then somewhere in your render function have something like this.
render() {
  ...
  {
    this.props.data.allComments.map(comment => {
      const isNew = this.state.newCommentIds.has(comment.id);
      return <CommentComponent isNew={isNew} comment={comment} />
    })
  }
  ...
}

上面的代码就在袖口上,所以你可能需要玩一下。希望这会有所帮助:)