Apollo-client: How to updateQueries when a subscription result arrives?

Created on 6 Feb 2017  路  8Comments  路  Source: apollographql/apollo-client

I have been trying to wrap my head around graphql subscriptions and how to implement them in my app. I want to do a simple messaging system, where a Salon and a Customer can communicate via WebSocket. I have a working subscribeToMore implementation, and using updateQuery, I can inject new data into a single query. But how can update other queries? Basically I want to do updateQueries for a subscription. How can we do that?

Issue #644 suggests to use a reducer, but I don't think this is a solution to my problem.

Anyways, this is my schema ATM

type Viewer {
  id: Int!
  username: String
  first_name: String
  last_name: String
  email: String
  messages: [Message]
  message(id: Int!): Message
}

type Message {
  id: Int!
  title: String
  text: String
  from_salon: Salon
  to_salon: Salon
  from_user: User
  to_user: User
  replies: [MessageReply]
}

type MessageReply {
  id: Int!
  text: String
  from_salon: Salon
  to_salon: Salon
  from_user: User
  to_user: User
}

And on the client I have three different views, each with it's own query:

AppContainer (root container, has subscription)

query viewer {
  viewer {
    id
    username
    first_name
    last_name
    email
  }
}

subscription newMessage($user_id: Int!) {
  newMessage(user_id: $user_id) {
    id title text
    from_salon { id title }
    to_salon { id title }
    from_user { id full_name }
    to_user { id full_name }
  }
}

UserMessageListContainer

query viewerMessageList {
  viewer {
    id
    messages {
      id title text
      from_salon { id title }
      to_salon { id title }
      from_user { id full_name }
      to_user { id full_name }
    }
  }
}

UserMessageContainer

query viewerMessage($id: Int!) {
  viewer {
    id
    message(id: $id) {
      id title text
      from_salon { id title }
      to_salon { id title }
      from_user { id full_name }
      to_user { id full_name }
      replies {
        id text
        from_salon { id title }
        to_salon { id title }
        from_user { id full_name }
        to_user { id full_name }
      }
    }
  }
}

So when AppContainer receives a newMessage via WebSocket, I want to update both viewerMessageList and viewerMessage as necessary. Or is there a better way?

Any help would be greatly appreciated ;)

All 8 comments

Might be related to #1224.

Ah, I see this is more about subscriptions. Here is an example: https://github.com/graphcool-examples/react-apollo-instagram-subscriptions-example

Of particular interest: https://github.com/graphcool-examples/react-apollo-instagram-subscriptions-example/blob/master/src/components/ListPage.js#L24

This updateQueries works just like updateQueries for mutations.

@marktani thanks for taking the time to answer.

This updateQueries works just like updateQueries for mutations.

You mean updateQuery works just like updateQueries for mutations, right? But it updates only a single query. What if I want to update other queries?

For example, I have a viewerMessages query that lists all messages and viewerMessage query that displays message details and conversation. When a new Message arrives via subscription, how can I update both these queries?

You mean updateQuery works just like updateQueries for mutations, right? But it updates only a single query. What if I want to update other queries?

Ahh, actually that didn't occur to me. Might be the case. But if you check the returned object it has the query name allPosts as the key. Did you try returning an object like this

return {
  viewerMessages: ...,
  viewerMessage: .... 
}

Let me check ... :)

In my top level AppContainer component I only have access to the viewer query, but not viewerMessages or viewerMessage. Problem is that updateQuery operates on a single query, but in my case I want to update other queries.

@HriBB we're working on a set of imperative store update functions (read a fragment from the store, write a fragment to the store). Hopefully you'll be able to use that for your problem. You could still use reducer, you just have to write one for each query you want to update (it's essentially the same for updateQueries).

The imperative store functions are available for you to use today! https://dev-blog.apollodata.com/apollo-clients-new-imperative-store-api-6cb69318a1e3#.p44izsa28

If you are using react-apollo, then you may also want to consider using subscribeToMore: http://dev.apollodata.com/react/api.html#graphql-query-data.subscribeToMore

Was this page helpful?
0 / 5 - 0 ratings