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

Query consolidation #426

Open
luin opened this issue Feb 16, 2024 · 1 comment
Open

Query consolidation #426

luin opened this issue Feb 16, 2024 · 1 comment
Labels
core Feature requests related to core functionality

Comments

@luin
Copy link

luin commented Feb 16, 2024

Something like Batch HTTP Link, but instead of batching multiple queries into a single HTTP request, we should be able to consolidate them into one larger query.

Example

const Book = ({ id }) => {
  return <div>
    <BookAuthor bookId={id}>
    <BookContent bookId={id>
  </div>
};

const BookAuthorQuery = gql(`
  query BookAuthor {
    book(id: $id) {
      id
      author {
        id
        avatar
      }
    }
  }
`);

const BookAuthor = () => {
  const { data } = useQuery(BookAuthorQuery);
  return ...
};

const BookContentQuery = gql(`
  query BookContent {
    book(id: $id) {
      id
      content
      author {
        id
        name
      }
    }
  }
`)

const BookContent = () => {
  const { data } = useQuery(BookAuthorQuery);
  return ...
};

With the feature enabled, Apollo will only send one single query:

query {
    book(id: $id) {
      id
      content
      author {
        id
        avatar
        name
      }
    }
}

Reasons

Consolidate queries would improve the backend performance by reducing database hits. This sometimes can be done via prop drilling. However, it's not always possible in a real application as the components may not directly related and could be rendered in a different part of the application.

@jerelmiller jerelmiller added the core Feature requests related to core functionality label Feb 17, 2024
@jerelmiller
Copy link
Member

Hey @luin 👋

Thanks for the feature request!

To be totally transparent, in the future we will be moving away from recommending composition on useQuery hooks and instead will be recommending fragment composition and colocation for this kind of thing. I'd encourage you to take a look at that doc for more information. I'd encourage you to try and leverage this pattern first.

Using that approach, you can both avoid both network requests and ensure both components get the data they need by defining fragments for each of the child fragments and moving the useQuery call up to the parent:

const BookQuery = gql`
  query BookAuthor {
    book(id: $id) {
      id
      author {
        id
        ...BookAuthorFragment
      }
      ...BookContentFragment
    }
  }

  ${BookAuthor.fragments.author}
  ${BookAuthor.fragments.book}
`;

const Book = ({ id }) => {
  const { data } = useQuery(BookQuery, { variables: { id } });

  // loading state omitted for brevity

  return (
    <div>
      <BookAuthor {data.book.author}>
      <BookContent book={data.book}>
    </div>
  );
}



const BookAuthor = ({ author }) => {
  // do something with author
}

// NOTE: The `fragments` property is more of a convention than a requirement. 
// Feel free to use whatever convention you like most :)
BookAuthor.fragments = {
  author: gql`
    fragment BookAuthorFragment on Author {
      id
      avatar
      name
    }
  `
}

const BookContent = ({ book }) => {
  return // ...
};

BookContent.fragments = {
  book: gql`
    fragment BookContentFragment on book {
      id
      content
    }
  `
}

To be totally transparent, it is unlikely we will consider this feature in favor of the recommendation above. It's also VERY tricky to get right since we'd need to track renders across multiple components in order to make this work.

I'd highly encourage you to try this pattern! We'll have more official announcements/recommendations on the matter soon, so please be on the lookout for that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
core Feature requests related to core functionality
Projects
None yet
Development

No branches or pull requests

2 participants