A GraphQL client for React using modern context and hooks APIs that’s lightweight (< 4 kB) but powerful; the first Relay and Apollo alternative with server side rendering.
The exports can also be used to custom load, cache and server side render any data, even from non-GraphQL sources.
Note
For a Next.js project, see the
next-graphql-reactinstallation instructions.
For Node.js, to install graphql-react and its react peer dependency with npm, run:
npm install graphql-react react
For Deno and browsers, an example import map (realistically use 4 import maps, with optimal URLs for server vs client and development vs production):
{
"imports": {
"extract-files/": "https://unpkg.com/extract-files@13.0.0/",
"graphql-react/": "https://unpkg.com/graphql-react@20.0.0/",
"is-plain-obj": "https://unpkg.com/is-plain-obj@4.1.0/index.js",
"is-plain-obj/": "https://unpkg.com/is-plain-obj@4.1.0/",
"react": "https://esm.sh/react@18.2.0",
"react-waterfall-render/": "https://unpkg.com/react-waterfall-render@5.0.0/"
}
}These dependencies might not need to be in the import map, depending on what graphql-react modules the project imports from:
Polyfill any required globals (see Requirements) that are missing in your server and client environments.
Create a single Cache instance and use the component Provider to provide it for your app.
To server side render your app, use the function waterfallRender from react-waterfall-render.
graphql-reactexamples repo, a Deno Ruck web app deployed at graphql-react-examples.fly.dev.- Official Next.js example (often outdated as the Next.js team can be extremely slow to review and merge pull requests).
Here is a basic example using the GitHub GraphQL API, with tips commented:
import useAutoLoad from "graphql-react/useAutoLoad.mjs"; import useCacheEntry from "graphql-react/useCacheEntry.mjs"; import useLoadGraphQL from "graphql-react/useLoadGraphQL.mjs"; import useWaterfallLoad from "graphql-react/useWaterfallLoad.mjs"; import React from "react"; // The query is just a string; no need to use `gql` from `graphql-tag`. The // special comment before the string allows editor syntax highlighting, Prettier // formatting and linting. The cache system doesn’t require `__typename` or `id` // fields to be queried. const query = /* GraphQL */ ` query ($repoId: ID!) { repo: node(id: $repoId) { ... on Repository { stargazers { totalCount } } } } `; export default function GitHubRepoStars({ repoId }) { const cacheKey = `GitHubRepoStars-${repoId}`; const cacheValue = useCacheEntry(cacheKey); // A hook for loading GraphQL is available, but custom hooks for loading non // GraphQL (e.g. fetching from a REST API) can be made. const loadGraphQL = useLoadGraphQL(); const load = React.useCallback( () => // To be DRY, utilize a custom hook for each API your app loads from, e.g. // `useLoadGraphQLGitHub`. loadGraphQL( cacheKey, // Fetch URI. "https://api.github.com/graphql", // Fetch options. { method: "POST", headers: { "Content-Type": "application/json", Accept: "application/json", Authorization: `Bearer ${process.env.GITHUB_ACCESS_TOKEN}`, }, body: JSON.stringify({ query, variables: { repoId, }, }), }, ), [cacheKey, loadGraphQL, repoId], ); // This hook automatically keeps the cache entry loaded from when the // component mounts, reloading it if it’s staled or deleted. It also aborts // loading if the arguments change or the component unmounts; very handy for // auto-suggest components! useAutoLoad(cacheKey, load); // Waterfall loading can be used to load data when server side rendering, // enabled automagically by `next-graphql-react`. To learn how this works or // to set it up for a non-Next.js app, see: // https://github.com/jaydenseric/react-waterfall-render const isWaterfallLoading = useWaterfallLoad(cacheKey, load); // When waterfall loading it’s efficient to skip rendering, as the app will // re-render once this step of the waterfall has loaded. If more waterfall // loading happens in children, those steps of the waterfall are awaited and // the app re-renders again, and so forth until there’s no more loading for // the final server side render. return isWaterfallLoading ? null : cacheValue ? cacheValue.errors ? // Unlike many other GraphQL libraries, detailed loading errors are // cached and can be server side rendered without causing a // server/client HTML mismatch error. "Error!" : cacheValue.data.repo.stargazers.totalCount : // In this situation no cache value implies loading. Use the // `useLoadingEntry` hook to manage loading in detail. "Loading..."; }
Supported runtime environments:
- Node.js versions
^18.18.0 || ^20.9.0 || >=22.0.0. - Deno, importing from a CDN that might require an import map for dependencies.
- Browsers matching the Browserslist query
> 0.5%, not OperaMini all, not dead.
Consider polyfilling:
Non Deno projects must configure TypeScript to use types from the ECMAScript modules that have a // @ts-check comment:
compilerOptions.allowJsshould betrue.compilerOptions.maxNodeModuleJsDepthshould be reasonably large, e.g.10.compilerOptions.moduleshould be"node16"or"nodenext".
The npm package graphql-react features optimal JavaScript module design. It doesn’t have a main index module, so use deep imports from the ECMAScript modules that are exported via the package.json field exports:
Cache.mjsCacheContext.mjscacheDelete.mjscacheEntryDelete.mjscacheEntryPrune.mjscacheEntrySet.mjscacheEntryStale.mjscachePrune.mjscacheStale.mjsfetchGraphQL.mjsfetchOptionsGraphQL.mjsHYDRATION_TIME_MS.mjsHydrationTimeStampContext.mjsLoading.mjsLoadingCacheValue.mjsLoadingContext.mjsProvider.mjstypes.mjsuseAutoAbortLoad.mjsuseAutoLoad.mjsuseCache.mjsuseCacheEntry.mjsuseCacheEntryPrunePrevention.mjsuseLoadGraphQL.mjsuseLoading.mjsuseLoadingEntry.mjsuseLoadOnDelete.mjsuseLoadOnMount.mjsuseLoadOnStale.mjsuseWaterfallLoad.mjs