我的用例如下:使用Apollo,我如何區分新創建的對象?
我有一個使用GraphQL查詢獲取的註釋列表。當用戶寫入新評論時,它會使用GraphQL變種提交。然後我使用updateQueries
將新評論追加到列表中。
在用戶界面中,我想突出顯示新創建的註釋。我試圖在mutationResult
的新評論上添加屬性isNew: true
,但Apollo在將其保存到存儲之前刪除了屬性(我假設這是因爲在gql查詢中未請求isNew
字段)。
有什麼辦法可以達到這個目的嗎?
我的用例如下:使用Apollo,我如何區分新創建的對象?
我有一個使用GraphQL查詢獲取的註釋列表。當用戶寫入新評論時,它會使用GraphQL變種提交。然後我使用updateQueries
將新評論追加到列表中。
在用戶界面中,我想突出顯示新創建的註釋。我試圖在mutationResult
的新評論上添加屬性isNew: true
,但Apollo在將其保存到存儲之前刪除了屬性(我假設這是因爲在gql查詢中未請求isNew
字段)。
有什麼辦法可以達到這個目的嗎?
取決於「新創建的對象」是什麼意思。如果它是基於身份驗證的應用程序,並且用戶可以登錄,則可以將評論的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的前端應用程序狀態,或者甚至更簡單地通過在組件狀態下管理它。
阿波羅讓您可以選擇提供自己的REDEX商店。您可以允許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} />
})
}
...
}
上面的代碼恰到好處,所以你可能需要玩一下。希望這有助於:)
感謝您的回答。我目前正在做一些與你的答案非常相似的東西:)但是我正在尋找一個不太冒險的解決方案。 –
評論發表的日期是可用的? – user2864740
我不認爲使用日期是一個可靠的解決方案。你如何檢測評論是否是新的?你檢查它是否在過去的10秒內創建?或在過去的100毫秒?每個人都有自己的問題。 –
「isNew」在某個固定時間點添加到第一條評論。在此之前的每一條評論都不再是新鮮事。 – user2864740