Skip to main content

React Basic Usage

Using GraphQL data within React components is straightforward.

  • Updates components when data changes
  • (When enabled) Suspends components while data is being fetched

Prerequisites#

Make sure you've completed Getting Started first

"../gqless" refers to the generated client file/directory

Installation#

First install @gqless/react into your project's dependencies:

npm install @gqless/react

Usage#

In your previously generated client, you should have something like this:

You can remove some hooks / functions that you are not planning to use

For more information about the configuration of the client check here.

export const {
graphql,
useQuery,
useTransactionQuery,
useLazyQuery,
useRefetch,
prepareQuery,
useMutation,
useSubscription,
useMetaState,
prepareReactRender,
useHydrateCache,
} = createReactClient<GeneratedSchema>(client, {
defaults: {
// Set this flag as "true" if your usage involves React Suspense
// Keep in mind that you can overwrite it in a per-hook basis
suspense: false,
// Set this flag based on your needs
staleWhileRevalidate: false,
},
});
caution

We recommend you reading the caveats of React Usage

We can take a quick look at all those functions:

Query related#

For more information check here.

  • useQuery | Main hook that uses all the main design of gqless.
import { useQuery } from '../gqless';
export function Example() {
const { helloWorld } = useQuery();
return (
<div>
<p>{helloWorld}</p>
</div>
);
}
import { graphql, query } from '../gqless';
export const Example = graphql(
function Example() {
return (
<div>
<p>{query.helloWorld}</p>
</div>
);
},
{
suspense: {
fallback: 'Loading...',
},
}
);
  • useTransactionQuery | Alternative to graphql and useQuery that works via pre-defined functions, which allows for extra features that are not available in the previously mentioned functions, like for example, scoped queries, polling, conditional skipping.
import { useTransactionQuery } from '../gqless';
export function Example() {
const { data, isLoading } = useTransactionQuery((query) => {
return query.helloWorld;
});
return (
<div>
<p>{isLoading ? 'Loading...' : data}</p>
</div>
);
}
  • useLazyQuery | Queries meant to be called in response of events, like button clicks.
import { useLazyQuery } from '../gqless';
export function Example() {
const [getHelloWorld, { isLoading, isCalled, data }] = useLazyQuery(
(query) => {
return query.helloWorld;
}
);
if (isCalled) {
return <p>{isLoading ? 'Loading...' : data}</p>;
}
return <button onClick={() => getHelloWorld()}>Get Hello World</button>;
}
  • useRefetch | Refetch giving specific parts of the schema or via functions.
import { useRefetch, useQuery } from '../gqless';
function Example() {
const refetch = useRefetch();
const query = useQuery();
return (
<div>
<button
onClick={() => {
refetch(() => query.helloWorld);
}}
>
Refetch
</button>
<p>{query.helloWorld}</p>
</div>
);
}
import { useState } from 'react';
import { prepareQuery } from '../gqless';
const { preload, refetch, usePrepared } = prepareQuery((query) => {
return query.helloWorld;
});
function Example() {
const { data } = usePrepared();
return <p>{data}</p>;
}
function Container() {
const [show, setShow] = useState(false);
return (
<div>
<button
onClick={() => {
if (show) {
refetch();
} else {
preload();
}
}}
>
{show ? 'Refetch' : 'Show Example'}
</button>
{show && <Example />}
</div>
);
}

Mutation related#

For more information check here.

import { useState } from 'react';
import { useMutation } from '../gqless';
export function LoginComponent() {
const [login, { isLoading, data }] = useMutation(
(mutation, args: { email: string; password: string }) => {
const { user, error } = mutation.login({ args });
if (user) {
return {
name: user.name,
};
}
return {
error,
};
}
);
const [formData, setFormData] = useState(() => ({ email: '', password: '' }));
return (
<form>
<label>Email</label>
<input
value={formData.email}
onChange={(ev) => {
setFormData({
...formData,
email: ev.target.value,
});
}}
/>
<label>Password</label>
<input
value={formData.password}
onChange={(ev) => {
setFormData({
...formData,
password: ev.target.value,
});
}}
/>
<button
type="submit"
disabled={isLoading}
onClick={(ev) => {
ev.preventDefault();
login({ args: formData }).catch(console.error);
}}
>
Login
</button>
{data?.error ? <p>Error: {data.error}</p> : null}
</form>
);
}

Subscription related#

For more information check here.

import { useSubscription } from '../gqless';
export function Example() {
const { newNotification } = useSubscription();
if (newNotification) {
return (
<p>
New Notification: <b>{newNotification}</b>
</p>
);
}
return <p>Waiting for new notifications...</p>;
}

Meta related#

For more information check here.

  • useMetaState | Hook designed to inspect the React Client state, like error handling and fetching state.
import { useMetaState } from '../gqless';
export function Example() {
const { isFetching, errors } = useMetaState({
onError({ newError, isLastTry }) {
if (isLastTry) {
console.error(newError);
}
},
});
return (
<div>
{isFetching && <p>Fetching...</p>}
{errors && (
<>
<p>Errors!</p>
<ul>
{errors.map((error, key) => {
return <li key={key}>{error.message}</li>;
})}
</ul>
</>
)}
</div>
);
}

SSR related#

For more information check here.

Examples made for Next.js SSR Data Fetching

import { PropsWithServerCache } from '@gqless/react';
import { GetStaticProps } from 'next';
import { prepareReactRender, useHydrateCache, useQuery } from '../gqless';
export default function ExamplePage({ cacheSnapshot }: PropsWithServerCache) {
useHydrateCache({
cacheSnapshot,
// If it should refetch everything after the component is mounted
// By default 'shouldRefetch' is `false`
shouldRefetch: false,
});
const { helloWorld } = useQuery();
return <p>{helloWorld}</p>;
}
export const getStaticProps: GetStaticProps = async (_ctx) => {
const { cacheSnapshot } = await prepareReactRender(<ExamplePage />);
return {
props: {
cacheSnapshot,
},
};
};
Last updated on by Sam Denty