Relay Modern nested pagination

2020-06-06 06:57发布

问题:

I have a root query of songs, this is in a pagination container. I then have a nested property on songs called comments that I also want to be paginated because I don't want to load 10k comments for each song all at once.

songsContainer.js:

fragment songsContainer on Query {
    songs(
      first: $count
      after: $cursor
      genre: $genre
      filter: $filter
    ) @connection(key: "songsContainer_songs") {
      edges {
        node {
          audioId
          name
          coverImageUrl
          artist
          likes
          dislikes
          ...commentsContainer
        }
      }
    }
  }

const connectionConfig = {
  direction: 'forward',
  query: graphql`
    query songsContainerForwardQuery(
      $count: Int!
      $cursor: String
      $genre: String
      $filter: FilterInput
    ) {
      ...songsContainer
    }
  `,
  getVariables: (_, { count, cursor }) => ({
    count,
    cursor,
  }),
};

paginationContainer(fragments, connectionConfig);

commentsContainer.js

  fragment commentsContainer on Audio {
    comments(
      first: $count
      after: $cursor
      getReplies: $getReplies
    ) @connection(key: "commentsContainer_comments") {
      edges {
        node {
          commentId
          body
          date
          likes
          dislikes
          repliesCount
          originalComment {
            id
          }
          user {
            userName
          }
        }
      }
    }
  }

How do I write the connectionConfig for the comments? I tried this:

const connectionConfig = {
  direction: 'forward',
  query: graphql`
    query commentsContainerForwardQuery(
      $count: Int!
      $cursor: String
    ) {
      ...commentsContainer
    }
  `,
  getVariables: (_, { count, cursor }) => ({
    count,
    cursor,
  }),
};

But because the comments are nested on songs then it throws an error saying that the query doesn't exist on the Root.

回答1:

SongsContainer.js

createPaginationContainer(
  SongsContainer,
  {
    viewer: graphql`
      fragment SongsContainer_viewer on Query {
        id
        songs(first: $count, after: $cursor)
          @connection(key: "SongsContainer_songs", filters: []) {
          edges {
            cursor
            node {
              id
              ...SongItem_song
            }
          }
        }
      }
    `
  },
  {
    direction: 'forward',
    getConnectionFromProps(props) {
      return props.viewer && props.viewer.songs;
    },
    getFragmentVariables(prevVars, totalCount) {
      return {
        ...prevVars,
        count: totalCount
      };
    },
    getVariables(props, { count, cursor }, fragmentVariables) {
      return {
        count,
        cursor
      };
    },
    query: graphql`
      query SongsContainerQuery($count: Int!, $cursor: String) {
        viewer {
          ...SongsContainer_viewer
        }
      }
    `
  }
);

SongItem.js

createRefetchContainer(
  SongItem,
  {
    song: graphql`
      fragment SongItem_song on Audio
        @argumentDefinitions(
          count: { type: "Int", defaultValue: 20 }
          cursor: { type: "String", defaultValue: null }
        ) {
        id
        ...CommentsContainer_song
        # ...more pagination container other_song
      }
    `
  },
  graphql`
    query SongItemQuery($id: ID!, $count: Int!, $cursor: String) {
      song(id: $id) {
        ...SongItem_song @arguments(count: $count, cursor: $cursor)
      }
    }
  `
);

CommentsContainer.js

createPaginationContainer(
  CommentsContainer,
  {
    song: graphql`
      fragment CommentsContainer_song on Audio {
        id
        comments(first: $count, after: $cursor)
          @connection(key: "CommentsContainer_comments", filters: []) {
          edges {
            id
          }
        }
      }
    `
  },
  {
    direction: 'forward',
    getConnectionFromProps(props) {
      return props.song && props.song.comments;
    },
    getFragmentVariables(prevVars, totalCount) {
      return {
        ...prevVars,
        count: totalCount
      };
    },
    getVariables(props, { count, cursor }, fragmentVariables) {
      return {
        count,
        cursor,
        id: props.song.id
      };
    },
    query: graphql`
      query CommentsContainerQuery($id: ID!, $count: Int!, $cursor: String) {
        song(id: $id) {
          ...CommentsContainer_song
        }
      }
    `
  }
);