Primitive that generates a client and reactive GraphQL queries
| Stage | Category | Version | Last Updated |
|---|---|---|---|
| 3 | Network | 3.0.0-next.0 (next) | Aug 13, 2026 |
npm i @solid-primitives/graphql@nextCreates a reactive GraphQL query client.
How to use it
Import
import { createGraphQLClient, gql, request } from "@solid-primitives/graphql";// gql is a helper for creating GraphQL query strings// request is an additional function to perform GraphQL requests imperativelyUsing the client
createGraphQLClient takes 2 arguments:
url- target api endpoint, as string or signaloptions- optional, Options for thefetchfunction,headers, thefetchermethod etc.fetcher- A fetch function to replace the default one, that is Fetch API on browser andnode-fetchon server.headers- A headers object to be passed to thefetchfunction.
import { createGraphQLClient, gql } from "@solid-primitives/graphql";
const newQuery = createGraphQLClient("https://foobar.com/v1/api");const [data, { refetch }] = newQuery( gql` query data($path: ID!) { PageItem(id: $path) { content { body } } } `, { path: "home" },);Preventing immediate requests
Query function is based on createResource, so it can be deferred in the same way - by passing false to the variables.
const newQuery = createGraphQLClient("https://foobar.com/v1/api");const [queryVars, setQueryVars] = createSignal<boolean | object>(false);const [data, { refetch }] = newQuery(gql`...`, queryVars);
setQueryVars({ foo: bar }); // will fetch for the first timerefetch(); // will refetch the second timeProviding Response Type
// query function accepts type generic for the response:const [countries] = newQuery<{ countries: { name: string }[] }>(gql` query { countries { name code } }`);countries(); // T: { countries: { name: string }[] } | undefinedInitial value
By default the returned data type will be T | undefined, to make it always T you need to provide an initial value.
const [countries] = newQuery<{ countries: { name: string }[] }>( gql` query { countries { name code } } `, // no variables undefined, // resource options with the initial value { initialValue: { countries: [] }, },);countries(); // T: { countries: { name: string }[] }Reactive query variables
Variables passed to the query can be reactive. If they change, the resource will be refetched.
const [code, setCode] = createSignal("BR");const [data] = query( gql` query data($code: ID!) { country(code: $code) { name } } `, // function returning an object () => ({ code: code(), }),);File upload support
If the server supports the GraphQL multipart request specification it is possible to upload a File or a binary Blob of data by calling the multipartRequest function with the File/Blob instances in the variables variables.
This is especially useful for GraphQL mutations, because allows for binary uploads without the necessity to first encode the data to some text-based format like base64.
import { request, gql } from "@solid-primitives/graphql";
const result = multipartRequest( "https://foobar.com/v1/api", gql` mutation UploadImage($file: Upload!, $caption: String!) { uploadImage(file: $file, caption: $caption) { id } } `, { variables: { caption: "A nice image", file: inputElement.files[0] }, },);fetch on the server
When running on environments without Browser fetch, you should provide a fetcher to the options object, or add it to the global window object.
import nodeFetch from "node-fetch";import { createGraphQLClient, gql } from "@solid-primitives/graphql";
const newQuery = createGraphQLClient("https://foobar.com/v1/api", { fetcher: nodeFetch });Remember, just like with createResource, you will need an <ErrorBoundary> to catch the errors, even if they are accessible inside the resource. Otherwise, uncaught errors might disrupt your application.
Changelog
See CHANGELOG.md