graphql-dotnet / relay

A toolset for creating Relay.js compatible GraphQL servers in dotnet.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

When would we use GetById()?

MartinDawson opened this issue · comments

When inheriting NodeGraphType we need to implement GetById(string id). All of my implementations at the moment just throw NotImplementedException because they never seem to be used.

When would we use this method, it seems obsolete to me? Was this used in Relay Classic only?

It's called by Relay in certain situations (that are mysterious) via the node(id) query. But yeah the times it's called tend to be few and far between, but I'm nit comfortable removing it as it's part of the relay graphql "spec" where a node query root is required

I figured out why we use it and why it's super awesome @jquense.

Let's say that we have a song which has many comments.

We want pagination on the comments because we don't want to load all of them at once so we use paginationContainer. Here's what I used to do:

const fragments = graphql`
  fragment commentsContainer_audio on Audio {
    audioId
    comments(
      first: $count
      after: $cursor
    ) @connection(key: "commentsContainer_comments") {
      edges {
        node {
          commentId
          ...commentContainer_comment
        }
      }
      pageInfo {
        hasNextPage
      }
    }
  }
`;

const connectionConfig = {
  direction: 'forward',
  query: graphql`
    query commentsContainerForwardQuery(
      $id: Int!
      $count: Int!
      $cursor: String
    ) {
      song(id: $id) {
        ...commentsContainer_audio
      }
    }
  `,
  getVariables: (props, { count, cursor }) => ({
    count,
    cursor,
    id: props.audio.audioId,
  }),
};

I would have to add a custom endpoint on the server that returns a song just so I could get the remaining comments for it when using pagination. However if we use node() instead, you can do this:

const fragments = graphql`
  fragment commentsContainer_audio on Audio {
    id
    comments(
      first: $count
      after: $cursor
    ) @connection(key: "commentsContainer_comments") {
      edges {
        node {
          commentId
          ...commentContainer_comment
        }
      }
      pageInfo {
        hasNextPage
      }
    }
  }
`;

const connectionConfig = {
  direction: 'forward',
  query: graphql`
    query commentsContainerForwardQuery(
      $id: ID!
      $count: Int!
      $cursor: String
    ) {
      node(id: $id) {
        ...commentsContainer_audio
      }
    }
  `,
  getVariables: (props, { count, cursor }) => ({
    count,
    cursor,
    id: props.audio.id,
  }),
};

This works if every type you return implements the node interface which it should, i.e using : NodeGraphType<TSource>.
This way you don't have to keep defining custom endpoints that return a single object for each pagination.
This is also really useful when you have nested pagination, e.g songs -> comments -> replies.
Obviously the node id for relay needs to be the same as the one in your database for this to work and not something random.

It just works out of the box with this @jquense great library because the relay id gets mapped to the database id if you use Id(x => x.id). So yeah... don't remove it :).