Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Why does subscribeToMore don't allow for different variables from the query variables? #4246

Closed
AndresRodH opened this issue Dec 18, 2018 · 4 comments

Comments

@AndresRodH
Copy link

AndresRodH commented Dec 18, 2018

I'm working with react-apollo in TS and find it frustrating that I can't add a generic type for variables to the subscribeToMore function, but I can pass TSubscriptionData. I'm designing subscriptions that are very generic and top-level. Take this hypothetical schema

enum Operation {
  CREATE
  UPDATE
}

type Post {
  id: ID!
  authorId: ID!
  text: String!
}

type PostSubscriptionPayload {
  id: ID!
  operation: Operation!
  post: Post!
}

type Subscription {
  post(id: String, operation: Operation): PostSubscriptionPayload
}

type Query {
  allPosts(authorId: ID): [Post!]!
}

Now, I would like to implement a custom component that could be used to query all posts or all posts by an author

type Post = { id: string, authorId: string, text: string }
type Feed = { allPosts: Post[] }
type FeedVariables = { authorId?: string | null }
type FeedQueryProps = Omit<QueryProps<Feed, FeedVariables>, 'query'>

const FEED =  gql`
  query Feed($authorId: String) {
    allPosts(authorId: $authorId) {
      id
      text
      authorId
    }
  }
`

const FeedQuery: React.FC<FeedQueryProps> = props => (
  <Query<Feed, FeedVariables> 
    query={FEED}
    {...props}
  />
)

I would like to subcribe to posts using the subscribeToMore function here. The subscribeToMore function is typed like this in apollo-client:

subscribeToMore<TSubscriptionData = TData>(options: SubscribeToMoreOptions<TData, TVariables, TSubscriptionData>): () => void;

This makes it possible to give a the type to the response, which I would expect is an object with id, operation and post as properties. The implementation allows for the post subscription to be treated as a catch-all if there is no particular operation or a listener for a single event. However, if I try to do the following, it will complain because the variables type is not compatible.

// subscription document
const FEED_MASTER_SUBSCRIPTION = gql`
  subscription FeedMasterSubscription($authorId: String, $operation: Operation) {
    post(authorId: $authorId, operation: $operation) {
      id
      text
      authorId
    }
  }
`
type FeedSubscriptionPayload = {
  id: string
  operation: 'CREATE' | 'UPDATE'
  post: Post
}

export const AuthorPosts = () => (
  <FeedQuery>
    {({ subscribeToMore }) => {
      // I want this to be a catch-all for creates and updates
      const subscribeToPostUpdate = () =>
        subscribeToMore<FeedSubscriptionPayload>({
          document: FEED_MASTER_SUBSCRIPTION,
          variables: {
            // ✅this would pass because it's part of FeedVariables
            authorId: 'some-author-id',
          },
        })
      
      return <SomeComponent subscribeToPostUpdate={subscribeToPostUpdate} />
    }}
  </FeedQuery>
)

export const Home = () => (
  <FeedQuery>
    {({ subscribeToMore }) => {
      // I only want to merge new posts
      const subscribeToPostCreate = () =>
        // NOTE: I can ONLY pass the shape of the subscription data here
        subscribeToMore<FeedSubscriptionPayload>({
          document: FEED_MASTER_SUBSCRIPTION,
          variables: {
            // ❌Type '{ operation: string; }' is not assignable to type 'FeedVariables'.
            // Object literal may only specify known properties, and 'operation' does not exist in type
            // 'FeedVariables'
            operation: 'CREATE',
          },
        })
      
      return <SomeComponent subscribeToPostCreate={subscribeToPostCreate} />
    }}
  </FeedQuery>
)

Is there a reason why clients are not allowed to pass custom variables as well? Is there a better option than casting subscribeToMore to utilize my subscription without having to make individual subscriptions for every possible operation?

[email protected]
[email protected]

@audiolion
Copy link

Im running into this same issue

timhwang21 added a commit to timhwang21/apollo-client that referenced this issue Mar 20, 2019
timhwang21 added a commit to timhwang21/apollo-client that referenced this issue Mar 20, 2019
timhwang21 added a commit to timhwang21/apollo-client that referenced this issue Mar 20, 2019
timhwang21 added a commit to timhwang21/apollo-client that referenced this issue Mar 20, 2019
@timhwang21
Copy link
Contributor

I've run into this as well, and filed a PR for it. Would be great to have this fixed!

@AndresRodH
Copy link
Author

AndresRodH commented Mar 20, 2019

@timhwang21 awesome! You mind posting a link for the PR so I can follow it?

EDIT: PR #4608

timhwang21 added a commit to timhwang21/apollo-client that referenced this issue Apr 6, 2019
timhwang21 added a commit to timhwang21/apollo-client that referenced this issue Apr 6, 2019
@hwillson
Copy link
Member

Please try a recent version of @apollo/client and let us know if this issue is still happening. Thanks!

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Feb 16, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants