我的用例如下:
我有一个使用 GraphQL 查询获取的评论列表。当用户编写新评论时,它会使用 GraphQL 突变提交。然后我updateQueries
用来将新评论附加到列表中。
在 UI 中,我想突出显示新创建的评论。我试图isNew: true
在 中的新评论上添加一个属性mutationResult
,但 Apollo 在将其保存到商店之前删除了该属性(我认为这是因为isNew
在 gql 查询中未请求该字段)。
有什么办法可以做到这一点?
我的用例如下:
我有一个使用 GraphQL 查询获取的评论列表。当用户编写新评论时,它会使用 GraphQL 突变提交。然后我updateQueries
用来将新评论附加到列表中。
在 UI 中,我想突出显示新创建的评论。我试图isNew: true
在 中的新评论上添加一个属性mutationResult
,但 Apollo 在将其保存到商店之前删除了该属性(我认为这是因为isNew
在 gql 查询中未请求该字段)。
有什么办法可以做到这一点?
取决于“新创建的对象”是什么意思。如果是基于身份验证的应用程序,用户可以登录,您可以将create_date
评论的last_online
日期与用户的某个日期进行比较。如果用户未被强制创建帐户,您可以将此类信息存储在本地存储或 cookie 中(当他/她上次访问该网站时)。
另一方面,如果您考虑实时更新评论列表,我建议您graphql-subscriptions
使用websockets
. pub-sub
它通过使用机制为您提供用户界面中的反应性。简单用例 - 每当向帖子添加新评论时,都会通知每个用户/查看者,评论可以附加到评论列表并以您想要的方式突出显示。
为了实现这一点,您可以创建一个subscription
被调用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
使用的机制websockets
,有必要在你的主服务器旁边创建这样一个服务器。您可以使用该subscriptions-transport-ws
模块。
这种解决方案的最大优点是它在您的应用程序中提供了反应性(实时更改应用于帖子下方的评论列表等)。我希望这对于您的用例来说可能是一个不错的选择。
我可以看到这是通过几种方式完成的。你是对的,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} />
})
}
...
}
上面的代码是即兴的,所以你可能需要玩一下。希望这可以帮助 :)