GraphQL Upload#
In GQty you can add File Upload
support easily, following the GraphQL multipart request specification.
Preparation#
Normally, in the API servers, they implement graphql-upload, which could be implemented with mercurius-upload for Mercurius, or in GraphQL EZ with the GraphQL Upload EZ Plugin.
Meanwhile in the client, to follow the GraphQL multipart spec, you can easily use extract-files.
yarn add extract-files@11.0.0
yarn add -D @types/extract-files@8.1.1
pnpm add extract-files@11.0.0
pnpm add -D @types/extract-files@8.1.1
npm install extract-files@11.0.0
npm install -D @types/extract-files@8.1.1
And then, use it in your QueryFetcher
, like the following example:
Compatible with browser's File and Blob, and React Native using ReactNativeFile
import { extractFiles } from 'extract-files';
// ...
const queryFetcher: QueryFetcher = async function (query, variables) {
const extracted = extractFiles({
query,
variables,
});
if (extracted.files.size > 0) {
const form = new FormData();
form.append('operations', JSON.stringify(extracted.clone));
const map: Record<number, string[]> = {};
let i = 0;
extracted.files.forEach((paths) => {
map[++i] = paths;
});
form.append('map', JSON.stringify(map));
i = 0;
extracted.files.forEach((_paths, file) => {
form.append(++i + '', file as File);
});
const response = await fetch('/api/graphql', {
method: 'POST',
headers: {},
body: form,
mode: 'cors',
});
const json = await response.json();
return json;
}
// Fallback to regular queries
const response = await fetch('/api/graphql', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
query,
variables,
}),
mode: 'cors',
});
const json = await response.json();
return json;
};
Usage#
Core#
Since the images are not serializable, GQty might be confused while
using them, that's why you have to specify a special option nonSerializableVariables
in your resolved
s
import { resolved, mutation } from '../gqty';
resolved(
() => {
return mutation.uploadFile({
file,
})!;
},
{
//...
// You should specify this flag
nonSerializableVariables: true,
}
)
.then((data) => {
// ...
})
.catch((error) => {
// ...
});
React#
Since the images are not serializable, GQty might be confused while
using them, that's why you have to specify a special option nonSerializableVariables
in your useMutation
s
const [uploadFile, { isLoading, data, error }] = useMutation(
(mutation, file: File) => {
return mutation.uploadFile({
file,
})!;
},
{
// ...
// You should specify this flag
nonSerializableVariables: true,
}
);