Capítulo 7 de 80

Chapter 7: GraphQL

Core Idea

Because TanStack Query is built on plain Promises, any GraphQL client that returns a Promise (e.g. graphql-request) works as a queryFn with no special integration — pairing it with GraphQL Code Generator gives fully-typed operations.

Key Concepts

  • Protocol-agnostic by design: queryFn just needs to return a Promise; GraphQL is one option among REST/gRPC/anything-async, not a first-class special case.
  • No normalized caching: this is the one deliberate trade-off vs. Apollo — most apps don't need it as much as they assume, but it's a real gap for schemas that benefit heavily from entity normalization.
  • Type-safe path: graphql-request + GraphQL Code Generator's graphql() tag produces a typed document; passing it to request() inside queryFn gives a fully-typed data with no manual typing.

Code Examples

import request from 'graphql-request'
import { graphql } from './gql/gql'

const allFilmsQuery = graphql(/* GraphQL */ `
  query allFilmsWithVariablesQuery($first: Int!) {
    allFilms(first: $first) { edges { node { id title } } }
  }
`)

function App() {
  const { data } = useQuery({
    queryKey: ['films'],
    queryFn: () => request('https://swapi-graphql.netlify.app/.netlify/functions/index', allFilmsQuery, { first: 10 }),
  })
}
  • What it demonstrates: a typed GraphQL query used as a normal queryFn — no adapter or special hook needed.

Key Takeaways

  1. Treat GraphQL as just another async transport — the query/mutation/invalidation model from earlier chapters applies unchanged.
  2. Reach for Apollo instead only when normalized entity caching is a genuine, proven requirement, not a default assumption.

Connects To

  • Comparison: the normalized-caching trade-off discussed against Apollo.
  • Query Functions: the general contract (queryFn returns a Promise) that makes this integration trivial.