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-react
installation 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/[email protected]/",
"graphql-react/": "https://unpkg.com/[email protected]/",
"is-plain-obj": "https://unpkg.com/[email protected]/index.js",
"is-plain-obj/": "https://unpkg.com/[email protected]/",
"react": "https://esm.sh/[email protected]",
"react-waterfall-render/": "https://unpkg.com/[email protected]/"
}
}
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-react
examples 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.allowJs
should betrue
.compilerOptions.maxNodeModuleJsDepth
should be reasonably large, e.g.10
.compilerOptions.module
should 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.mjs
CacheContext.mjs
cacheDelete.mjs
cacheEntryDelete.mjs
cacheEntryPrune.mjs
cacheEntrySet.mjs
cacheEntryStale.mjs
cachePrune.mjs
cacheStale.mjs
fetchGraphQL.mjs
fetchOptionsGraphQL.mjs
HYDRATION_TIME_MS.mjs
HydrationTimeStampContext.mjs
Loading.mjs
LoadingCacheValue.mjs
LoadingContext.mjs
Provider.mjs
types.mjs
useAutoAbortLoad.mjs
useAutoLoad.mjs
useCache.mjs
useCacheEntry.mjs
useCacheEntryPrunePrevention.mjs
useLoadGraphQL.mjs
useLoading.mjs
useLoadingEntry.mjs
useLoadOnDelete.mjs
useLoadOnMount.mjs
useLoadOnStale.mjs
useWaterfallLoad.mjs