What is apollo-upload-client?
The apollo-upload-client package is a client for Apollo GraphQL that enables file uploads via GraphQL mutations. It extends Apollo Client to support file uploads using the GraphQL multipart request specification.
What are apollo-upload-client's main functionalities?
File Upload
This feature allows you to upload files via GraphQL mutations. The code sample demonstrates how to set up an Apollo Client with the upload link and perform a file upload mutation.
const { ApolloClient, InMemoryCache, HttpLink } = require('@apollo/client');
const { createUploadLink } = require('apollo-upload-client');
const link = createUploadLink({ uri: 'http://localhost:4000/graphql' });
const client = new ApolloClient({
link,
cache: new InMemoryCache()
});
const UPLOAD_FILE = gql`
mutation($file: Upload!) {
uploadFile(file: $file) {
url
}
}
`;
const file = new File(['foo'], 'foo.txt', {
type: 'text/plain',
});
client.mutate({
mutation: UPLOAD_FILE,
variables: { file }
}).then(response => {
console.log(response.data.uploadFile.url);
});
Other packages similar to apollo-upload-client
apollo-link-rest
This package allows you to call REST endpoints from Apollo Client. While it does not specifically handle file uploads, it can be used to integrate RESTful file upload endpoints with Apollo Client.
graphql-request
A minimal GraphQL client that supports file uploads via the multipart request specification. It is more lightweight compared to apollo-upload-client and can be used in environments where a full Apollo Client setup is not required.
Enhances Apollo for intuitive file uploads via GraphQL mutations or queries. Use with Apollo upload server.
Setup
Install with npm:
npm install apollo-upload-client
React Native installs packages without their dev dependencies and unconventionally Babel is run over node_modules
. Babel errors when it tries to respect config found in this package with presets and plugins absent. To overcome this install these dev dependencies (at versions matching package.json
):
npm install --save-dev babel-preset-env babel-preset-stage-0 babel-plugin-transform-runtime
Setup Apollo client with a special network interface:
import ApolloClient from 'apollo-client'
import { createNetworkInterface } from 'apollo-upload-client'
const client = new ApolloClient({
networkInterface: createNetworkInterface({
uri: '/graphql'
})
})
Alternatively enable query batching:
import ApolloClient from 'apollo-client'
import { createBatchNetworkInterface } from 'apollo-upload-client'
const client = new ApolloClient({
networkInterface: createBatchNetworkInterface({
uri: '/graphql',
batchInterval: 10
})
})
Also setup Apollo upload server.
Usage
Once setup, you will be able to use File
objects, FileList
objects, or File
arrays within query or mutation input variables.
For React Native, any object with the properties name
, type
and uri
within variables will be treated as a file.
The files upload to a temp directory; the paths and metadata will be available under the variable name in the resolver. See the server usage.
Single file
See server usage for this example.
import React from 'react'
import { graphql, gql } from 'react-apollo'
export default graphql(gql`
mutation updateUserAvatar($userId: String!, $avatar: File!) {
updateUserAvatar(userId: $userId, avatar: $avatar) {
id
}
}
`)(({ userId, mutate }) => {
const handleChange = ({ target }) => {
if (target.validity.valid) {
mutate({
variables: {
userId,
avatar: target.files[0]
}
}).then(({ data }) => console.log('Mutation response:', data))
}
}
return (
<input
type="file"
accept={'image/jpeg,image/png'}
required
onChange={handleChange}
/>
)
})
Multiple files
See server usage for this example.
import React from 'react'
import { graphql, gql } from 'react-apollo'
export default graphql(gql`
mutation updateGallery($galleryId: String!, $images: [File!]!) {
updateGallery(galleryId: $galleryId, images: $images) {
id
}
}
`)(({ galleryId, mutate }) => {
const handleChange = ({ target }) => {
if (target.validity.valid) {
mutate({
variables: {
galleryId,
images: target.files
}
}).then(({ data }) => console.log('Mutation response:', data))
}
}
return (
<input
type="file"
accept={'image/jpeg,image/png'}
multiple
required
onChange={handleChange}
/>
)
})
Inspiration