GraphQL
Refine provides a data provider for GraphQL APIs that has all the features of Refine without giving up the GraphQL features.
- This library uses
graphql-request@5
to handle the requests. - To build queries and mutations,
gql-query-builder
is used. - You can also use
graphql-tag
to write your queries and mutations. - To learn more about data fetching in Refine, check out the Data Fetching guide.
Installation
- npm
- pnpm
- yarn
npm i @refinedev/graphql
pnpm add @refinedev/graphql
yarn add @refinedev/graphql
Usage
We'll create a GraphQL Client with our API url and pass it to the dataProvider
function to create a data provider.
import Refine from "@refinedev/core";
import dataProvider, { GraphQLClient } from "@refinedev/graphql";
const client = new GraphQLClient("https://api.example.com/graphql");
const App = () => (
<Refine
dataProvider={dataProvider(client)}
>
{/* ... */}
</Refine>
);
Realtime
@refinedev/graphql
also provides a liveProvider
to enable realtime features of Refine. These features are powered by GraphQL subscriptions and uses graphql-ws
to handle the connections.
import Refine from "@refinedev/core";
import dataProvider, {
GraphQLClient,
liveProvider,
graphqlWS,
} from "@refinedev/graphql";
const client = new GraphQLClient("https://api.example.com/graphql");
const wsClient = graphqlWS.createClient({
url: "wss://api.example.com/graphql",
});
const App = () => (
<Refine
dataProvider={dataProvider(client)}
liveProvider={liveProvider(wsClient)}
options={{ liveMode: "auto" }}
>
{/* ... */}
</Refine>
);
Queries and Mutations
You can use graphql-tag
to write your queries and mutations.
Refine hooks' meta
object has optional gqlQuery
and gqlMutation
properties, you can use them to write your queries and mutations.
As a best-practice, we suggest writing your queries/mutations in a separate file, next to the component that uses it.
import gql from "graphql-tag";
const POSTS_LIST_QUERY = gql`
query PostList($where: JSON, $sort: String) {
posts(where: $where, sort: $sort) {
id
title
content
category {
id
}
}
}
`;
const POST_CREATE_MUTATION = gql`
mutation createPost($input: createPostInput!) {
createPost(input: $input) {
id
title
content
category {
id
}
}
}
`;
import { useList } from "@refinedev/core";
import { POSTS_LIST_QUERY } from "./queries";
export const PostListPage () => {
const { data } = useList({
resource: "posts",
meta: { gqlQuery: POSTS_LIST_QUERY },
});
return (
<div>
{/* ... */}
</div>
);
}
import { useForm } from "@refinedev/core";
import { POST_CREATE_MUTATION } from "./queries";
export const PostCreatePage () => {
const { formProps } = useForm({
resource: "posts",
meta: { gqlMutation: POST_CREATE_MUTATION },
});
return (
<div>
{/* ... */}
</div>
);
}
Authentication
If your API uses authentication, you can easily provide a custom fetcher for the requests and handle the authentication logic there. When creating a GraphQL Client, you can pass a fetch
function to the client options. This function will be used to append the authentication headers to the requests.
import graphqlDataProvider, { GraphQLClient } from "@refinedev/graphql";
const client = new GraphQLClient(API_URL, {
fetch: (url: string, options: RequestInit) => {
return fetch(url, {
...options,
headers: {
...options.headers,
/**
* For demo purposes, we're using `localStorage` to access the token.
* You can use your own authentication logic here.
* In real world applications, you'll need to handle it in sync with your `authProvider`.
*/
Authorization: `Bearer ${localStorage.getItem("token")}`,
},
});
},
});
/**
* Create the data provider with the custom client.
*/
const dataProvider = graphqlDataProvider(client);
GraphQL Query Builder
GraphQL Query Builder allows us to build queries and mutations. The getList
, getMany
, and, getOne
methods in our dataProvider
generate a query to send a request. On the other hand, the create
, createMany
, update
, updateMany
, deleteOne
, and, deleteMany
methods generate a mutation to send a request.
In order to create a GraphQL query, our dataProvider
has to take some options, such as specifying which fields will come in response, we pass these options to our dataProvider
methods with MetaDataQuery
.
Refer to the meta
properties for detailed usage. →
Hooks and components that support meta
:
Usage with Inferencer
You can also use @refinedev/inferencer
package to generate sample codes for your views. Since the GraphQL data providers rely on meta
fields, you'll need to provide some meta
values beforehand and then Inferencer will use these values to infer the fields of the data provider's response, generate a code and a preview.
Example
npm create refine-app@latest -- --example data-provider-nestjs-query