2017-02-20 18 views
1

我的用例如下:使用Apollo,我如何區分新創建的對象?

我有一個使用GraphQL查詢獲取的註釋列表。當用戶寫入新評論時,它會使用GraphQL變種提交。然後我使用updateQueries將新評論追加到列表中。

在用戶界面中,我想突出顯示新創建的註釋。我試圖在mutationResult的新評論上添加屬性isNew: true,但Apollo在將其保存到存儲之前刪除了屬性(我假設這是因爲在gql查詢中未請求isNew字段)。

有什麼辦法可以達到這個目的嗎?

+0

評論發表的日期是可用的? – user2864740

+0

我不認爲使用日期是一個可靠的解決方案。你如何檢測評論是否是新的?你檢查它是否在過去的10秒內創建?或在過去的100毫秒?每個人都有自己的問題。 –

+0

「isNew」在某個固定時間點添加到第一條評論。在此之前的每一條評論都不再是新鮮事。 – user2864740

回答

0

取決於「新創建的對象」是什麼意思。如果它是基於身份驗證的應用程序,並且用戶可以登錄,則可以將評論的create_date與用戶的某個last_online日期進行比較。如果用戶沒有被迫創建帳戶,則可以將這些信息存儲在本地存儲或Cookie中(上次訪問該網站時)。


在另一方面,如果你仔細想想的評論列表實時更新的,我建議你看一看graphql-subscriptions與使用websockets。它通過使用pub-sub機制在您的用戶界面中爲您提供反應性。簡單用例 - 每當向帖子添加新評論時,每個用戶/查看者都會收到相關通知,評論可以添加到評論列表中並以您需要的方式突出顯示。

爲了實現這一點,你可以創建一個名爲subscriptionnewCommentAdded,該客戶端將訂閱和每一個正在創建一個新的評論時,應用程序的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模塊。

這種解決方案的最大優勢在於它在您的應用程序中提供反應性(實時更改應用於評論列表,下面的文章等)。我希望這可能是您的使用案例的不錯選擇。

+0

感謝您花時間回答。我實際上對來自服務器的新評論不感興趣。我只關心當前用戶正在撰寫的評論。 –

0

我可以看到這是通過幾種方式完成的。你是對的,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} /> 
    }) 
    } 
    ... 
} 

上面的代碼恰到好處,所以你可能需要玩一下。希望這有助於:)

+0

感謝您的回答。我目前正在做一些與你的答案非常相似的東西:)但是我正在尋找一個不太冒險的解決方案。 –

相關問題