Handling uploads with React | laravel-medialibrary | Spatie

 SPATIE

  Laravel Media Library
========================

spatie.be/open-source

  [Docs](https://spatie.be/docs)  [Laravel-medialibrary](https://spatie.be/docs/laravel-medialibrary/v9)  Handling-uploads-with-media-library-pro  Handling uploads with React

 Version   v11   v10   v9   v8   v7   v6   v5   v4   v3

 Other versions for crawler [v11](https://spatie.be/docs/laravel-medialibrary/v11) [v10](https://spatie.be/docs/laravel-medialibrary/v10) [v9](https://spatie.be/docs/laravel-medialibrary/v9) [v8](https://spatie.be/docs/laravel-medialibrary/v8) [v7](https://spatie.be/docs/laravel-medialibrary/v7) [v6](https://spatie.be/docs/laravel-medialibrary/v6) [v5](https://spatie.be/docs/laravel-medialibrary/v5) [v4](https://spatie.be/docs/laravel-medialibrary/v4) [v3](https://spatie.be/docs/laravel-medialibrary/v3)

- [ Introduction ](https://spatie.be/docs/laravel-medialibrary/v9/introduction)
- [ Support us ](https://spatie.be/docs/laravel-medialibrary/v9/support-us)
- [ Base installation ](https://spatie.be/docs/laravel-medialibrary/v9/installation-setup)
- [ Questions and issues ](https://spatie.be/docs/laravel-medialibrary/v9/questions-issues)
- [ Requirements ](https://spatie.be/docs/laravel-medialibrary/v9/requirements)
- [ Upgrading ](https://spatie.be/docs/laravel-medialibrary/v9/upgrading)
- [ Changelog ](https://spatie.be/docs/laravel-medialibrary/v9/changelog)
- [ Troubleshooting ](https://spatie.be/docs/laravel-medialibrary/v9/troubleshooting)
- [ About us ](https://spatie.be/docs/laravel-medialibrary/v9/about-us)

Basic usage
-----------

- [ Preparing your model ](https://spatie.be/docs/laravel-medialibrary/v9/basic-usage/preparing-your-model)
- [ Associating files ](https://spatie.be/docs/laravel-medialibrary/v9/basic-usage/associating-files)
- [ Retrieving media ](https://spatie.be/docs/laravel-medialibrary/v9/basic-usage/retrieving-media)

Working with media collections
------------------------------

- [ Simple media collections ](https://spatie.be/docs/laravel-medialibrary/v9/working-with-media-collections/simple-media-collections)
- [ Defining media collections ](https://spatie.be/docs/laravel-medialibrary/v9/working-with-media-collections/defining-media-collections)

Converting images
-----------------

- [ Defining conversions ](https://spatie.be/docs/laravel-medialibrary/v9/converting-images/defining-conversions)
- [ Retrieving converted images ](https://spatie.be/docs/laravel-medialibrary/v9/converting-images/retrieving-converted-images)
- [ Optimizing converted images ](https://spatie.be/docs/laravel-medialibrary/v9/converting-images/optimizing-converted-images)
- [ Regenerating images ](https://spatie.be/docs/laravel-medialibrary/v9/converting-images/regenerating-images)

Handling uploads with Media Library Pro
---------------------------------------

- [ Introduction ](https://spatie.be/docs/laravel-medialibrary/v9/handling-uploads-with-media-library-pro/introduction)
- [ Installation ](https://spatie.be/docs/laravel-medialibrary/v9/handling-uploads-with-media-library-pro/installation)
- [ Processing uploads on the server ](https://spatie.be/docs/laravel-medialibrary/v9/handling-uploads-with-media-library-pro/processing-uploads-on-the-server)
- [ Handling uploads with Blade ](https://spatie.be/docs/laravel-medialibrary/v9/handling-uploads-with-media-library-pro/handling-uploads-with-blade)
- [ Handling uploads with Livewire ](https://spatie.be/docs/laravel-medialibrary/v9/handling-uploads-with-media-library-pro/handling-uploads-with-livewire)
- [ Handling uploads with Vue ](https://spatie.be/docs/laravel-medialibrary/v9/handling-uploads-with-media-library-pro/handling-uploads-with-vue)
- [ Handling uploads with React ](https://spatie.be/docs/laravel-medialibrary/v9/handling-uploads-with-media-library-pro/handling-uploads-with-react)
- [ Creating custom Vue components ](https://spatie.be/docs/laravel-medialibrary/v9/handling-uploads-with-media-library-pro/creating-custom-vue-components)
- [ Creating custom React components ](https://spatie.be/docs/laravel-medialibrary/v9/handling-uploads-with-media-library-pro/creating-custom-react-components)
- [ Customizing CSS ](https://spatie.be/docs/laravel-medialibrary/v9/handling-uploads-with-media-library-pro/customizing-css)

Responsive images
-----------------

- [ Getting started with responsive images ](https://spatie.be/docs/laravel-medialibrary/v9/responsive-images/getting-started-with-responsive-images)
- [ Using your own width calculator ](https://spatie.be/docs/laravel-medialibrary/v9/responsive-images/using-your-own-width-calculator)
- [ Customizing the rendered html ](https://spatie.be/docs/laravel-medialibrary/v9/responsive-images/customizing-the-rendered-html)
- [ Generating your own tiny placeholder ](https://spatie.be/docs/laravel-medialibrary/v9/responsive-images/generating-your-own-tiny-placeholder)
- [ Responsive images demo ](https://spatie.be/docs/laravel-medialibrary/v9/responsive-images/demo)

Converting other file types
---------------------------

- [ Using image generators ](https://spatie.be/docs/laravel-medialibrary/v9/converting-other-file-types/using-image-generators)
- [ Creating a custom image generator ](https://spatie.be/docs/laravel-medialibrary/v9/converting-other-file-types/creating-a-custom-image-generator)

Downloading media
-----------------

- [ Downloading a single file ](https://spatie.be/docs/laravel-medialibrary/v9/downloading-media/downloading-a-single-file)
- [ Downloading multiple files ](https://spatie.be/docs/laravel-medialibrary/v9/downloading-media/downloading-multiple-files)

Advanced usage
--------------

- [ Working with multiple filesystems ](https://spatie.be/docs/laravel-medialibrary/v9/advanced-usage/working-with-multiple-filesystems)
- [ Using custom properties ](https://spatie.be/docs/laravel-medialibrary/v9/advanced-usage/using-custom-properties)
- [ Storing media specific manipulations ](https://spatie.be/docs/laravel-medialibrary/v9/advanced-usage/storing-media-specific-manipulations)
- [ Using your own model ](https://spatie.be/docs/laravel-medialibrary/v9/advanced-usage/using-your-own-model)
- [ Outputting media ](https://spatie.be/docs/laravel-medialibrary/v9/advanced-usage/outputting-media)
- [ Rendering media ](https://spatie.be/docs/laravel-medialibrary/v9/advanced-usage/rendering-media)
- [ Using a custom directory structure ](https://spatie.be/docs/laravel-medialibrary/v9/advanced-usage/using-a-custom-directory-structure)
- [ Ordering media ](https://spatie.be/docs/laravel-medialibrary/v9/advanced-usage/ordering-media)
- [ Using a custom media downloader ](https://spatie.be/docs/laravel-medialibrary/v9/advanced-usage/using-a-custom-media-downloader)
- [ Moving media ](https://spatie.be/docs/laravel-medialibrary/v9/advanced-usage/moving-media)
- [ Consuming events ](https://spatie.be/docs/laravel-medialibrary/v9/advanced-usage/consuming-events)
- [ Generating custom urls ](https://spatie.be/docs/laravel-medialibrary/v9/advanced-usage/generating-custom-urls)
- [ Overriding default filesystem behavior ](https://spatie.be/docs/laravel-medialibrary/v9/advanced-usage/overriding-the-default-filesystem-behaviour)
- [ Naming generated files ](https://spatie.be/docs/laravel-medialibrary/v9/advanced-usage/naming-files)
- [ Disable CDN ](https://spatie.be/docs/laravel-medialibrary/v9/advanced-usage/disable-cdn)
- [ Customising Database Connections ](https://spatie.be/docs/laravel-medialibrary/v9/advanced-usage/customising-database-connections)

API
---

- [ Adding files ](https://spatie.be/docs/laravel-medialibrary/v9/api/adding-files)
- [ Defining conversions ](https://spatie.be/docs/laravel-medialibrary/v9/api/defining-conversions)

      You are viewing the documentation for **an older version** of this package. You can check the version you are using with the following command:

 `                                    composer show spatie/laravel-medialibrary                                                                                                                                                                                                                                    `

Handling uploads with React
===========================

###  On this page

1. [ Demo application ](#content-demo-application)
2. [ Basic setup ](#content-basic-setup)
3. [ Your first components ](#content-your-first-components)
4. [ Validation rules ](#content-validation-rules)
5. [ Translations ](#content-translations)
6. [ Usage in Next.js ](#content-usage-in-nextjs)
7. [ Props ](#content-props)

Media Library Pro provides beautiful UI components for React. They pack a lot of features: temporary uploads, custom property inputs, frontend validation, and robust error handling.

The `MediaLibraryAttachment` component can upload one or more files with little or no extra information. The attachment component is a lightweight solution for small bits of UI like avatar fields.

![Screenshot of the MediaLibraryAttachment React component](/docs/laravel-medialibrary/v9/images/pro/attachment.png)

The `MediaLibraryCollection` component can upload multiple files with custom properties. The collection component shines when you need to manage media, like in backoffices.

![Screenshot of the MediaLibraryCollection React component](/docs/laravel-medialibrary/v9/images/pro/collection.png)

If neither of these fit the bill, we've exposed a set of APIs for you to be bold and [roll your own components](./creating-custom-react-components).

Demo application
--------------------------------------------------------------------------------------------------------

In [this repo on GitHub](https://github.com/spatie/laravel-medialibrary-pro-app), you'll find a demo Laravel application in which you'll find examples of how to use Media Library Pro with React.

If you are having troubles using the components, take a look in that app to see how we've done it.

Basic setup
-----------------------------------------------------------------------------------------

First, the server needs to be able to catch your incoming uploads. Use the `mediaLibrary` macro in your routes file.

```
// Probably routes/web.php
Route::mediaLibrary();
```

The macro will register a route on `/media-library-pro/uploads`, which is used by the Vue components by default. You can change the prefix by passing it to the macro:

```
// Probably routes/web.php
Route::mediaLibrary('my-custom-url');
```

This will register a route at `/my-custom-url/uploads` instead.

### Customizing the upload endpoint

The React components post data to `/media-library-pro/uploads` by default. If you registered the controller on a different URL, pass it to the `routePrefix` prop of your React components.

```

```

### Importing the components

*If you're developing a project where you don't have access to composer, you can download the package through GitHub Packages: [installation steps](./installation#usage-in-a-frontend-repository). [Read this for usage in Next.js](#usage-in-nextjs)*

The components are located in `vendor/spatie/laravel-medialibrary-pro/resources/js` when you install the package through Composer. This makes for very long import statements, which you can clean up by adding some configuration to your Webpack/Laravel Mix configuration.

**laravel-mix &gt;6**

```
// webpack.mix.js

mix.override((webpackConfig) => {
    webpackConfig.resolve.modules = [
        "node_modules",
        __dirname + "/vendor/spatie/laravel-medialibrary-pro/resources/js",
    ];
}
```

**laravel-mix &lt;6**

```
// webpack.mix.js

mix.webpackConfig({
    resolve: {
        modules: [
            "node_modules",
            __dirname + "/vendor/spatie/laravel-medialibrary-pro/resources/js",
        ],
    },
});
```

This will force Webpack to look in `vendor/spatie/laravel-medialibrary-pro/resources/js` when resolving imports, and allows you to shorten your import to this:

```
import { MediaLibraryAttachment } from "media-library-pro-react-attachment";
```

If you're using TypeScript, you will also have have to add this to your tsconfig:

```
// tsconfig.json

{
    "compilerOptions": {
        "paths": {
            "*": ["*", "vendor/spatie/laravel-medialibrary-pro/resources/js/*"]
        }
    }
}
```

Your first components
-----------------------------------------------------------------------------------------------------------------------

The most basic components have a `name` prop. This name will be used to identify the media when it's uploaded to the server.

```
// MyImageUploader.jsx

import { MediaLibraryAttachment } from "media-library-pro-react-attachment";
import { MediaLibraryCollection } from "media-library-pro-react-collection";

export default function MyImageUploader() {
    return (

            Submit

    );
}
```

### Passing an initial value

If your form modifies an existing set of media, you may pass it through in the `initialValue` prop.

You can retrieve your initial values in Laravel using `$yourModel->getMedia($collectionName);`, this will also take care of any `old` values after an invalid form submit.

```

    Submit

```

Under the hood, these components create hidden `` fields to keep track of the form values on submit. If you would like to submit your values asynchronously, refer to the [Asynchronously submit data](#content-asynchronously-submit-data) section.

### Setting validation rules

You'll probably want to validate what gets uploaded. Use the `validationRules` prop, and don't forget to pass Laravel's validation errors too. The validation errors returned from the server will find errors under the key used in your `name` prop.

```

    Submit

```

You can also set the maximum amount of images that users can be uploaded using the `max-items` prop. Don't forget to set the `multiple` prop for the attachment component.

```

    Submit

```

See the [Validation rules section](#validation-rules) for a complete list of all possible validation rules.

### Checking the upload state

The components keep track of whether they're ready to be submitted, you can use this to disable a submit button while a file is still uploading or when there are frontend validation errors. This value can be tracked by passing a listener method to the `onIsReadyToSubmitChange` prop. If you submit a form while a file is uploading, Laravel will return a HTTP 500 error with an `invalid uuid` message.

```
import { MediaLibraryAttachment } from "media-library-pro-react-attachment";

function AvatarComponent() {
    const [isReadyToSubmit, setIsReadyToSubmit] = useState(true);

    return(

        Submit
    )
}
```

### Using custom properties

The Media Library supports [custom properties](/docs/laravel-medialibrary/v9/advanced-usage/using-custom-properties) to be saved on a media item. The values for these can be chosen by your users. By default, the `MediaLibraryAttachment` component doesn't show any input fields, and the `MediaLibraryCollection` component only shows a `name` field, with the option to add more fields.

Use the `fieldsView` render prop to add some fields:

```
 (

                Name

                {getNameInputErrors().map((error) => (

                        {error}

                ))}

                Extra field

                {getCustomPropertyInputErrors("extra_field").map((error) => (

                        {error}

                ))}

    )}
/>
```

When you add an image to your collection, it will look like this.

![Screenshot of custom property](/docs/laravel-medialibrary/v9/images/pro/extra.png)

### Customizing the file properties

When uploading a file, some properties appear by default: its extension, filesize and a remove or download button (respectively for the attachment or collection component).

You can customize what is displayed here by using the `propertiesView` scoped slot:

```
 (
        {object.attributes.name}
    )}
/>
```

### Asynchronously submit data

If you don't want to use traditional form submits to send your data to the backend, you will have to keep track of the current value of the component using the `onChange` handler. The syntax is the same for all UI components.

```
import Axios from 'axios';

export function AvatarForm({ values }) {
    const [media, setMedia] = React.useState(values.media);
    const [validationErrors, setValidationErrors] = React.useState({});

    function submitForm() {
        Axios
            .post('endpoint', { media })
            .catch(error => setValidationErrors(error.data.errors));
    }

    return (

            Submit

    );
}
```

### Usage with Laravel Vapor

If you are planning on deploying your application to AWS using [Laravel Vapor](https://vapor.laravel.com/), you will need to do some extra configuration to make sure files are uploaded properly to an S3 bucket.

First off, make sure you have [enabled Vapor support in Laravel](./processing-uploads-on-the-server#enabling-vapor-support).

You will also need to set the `vapor` prop in your components.

```

```

If you edited Vapor's signed storage URL in Laravel, you will need to pass the new endpoint to your components in `vaporSignedStorageUrl`. It will use `/vapor/signed-storage-url` by default.

```

```

### Usage with Inertia

When using the components in repository that uses Inertia, the setup is very similar to the asynchronous setup.

```
import React, { useState } from "react";
import { MediaLibraryAttachment } from "media-library-pro-react-attachment";
import { usePage } from "@inertiajs/inertia-react";
import { Inertia } from "@inertiajs/inertia";

export default function AccountPage() {
    const { props } = usePage();
    const [avatar, setAvatar] = useState(props.values.avatar);

    function handleSubmit() {
        Inertia.post("", { avatar });
    }

    return (

                Submit

    );
}
```

Validation rules
--------------------------------------------------------------------------------------------------------

There are a couple of different ways to validate files on the frontend. These props are available to you: `validationRules`, `maxItems` and `beforeUpload`.

**validationRules**

In the `validationRules` object, we've got the `accept` property, which expects an array of MIME types as strings. Leave it empty to accept all types of files, set its value to `['image/*']` to accept any type of image, or choose your own set of rules using [MIME types](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types). Remember, the only valid MIME type of a JPEG/JPG is `image/jpeg`!

The `minSizeInKB` and `maxSizeInKB` properties set the minimum and maximum size of any individual file.

```

```

**maxItems**

Set the maximum amount of items in the collection/attachment component at any time.

```

```

**beforeUpload**

Pass a method to `beforeUpload` that accepts a [file](https://developer.mozilla.org/en-US/docs/Web/API/File) parameter. Return any value (or resolve a Promise with any value) from this function to upload the file. Throw an Error in this function to cause the file not to be uploaded, and display your error message.

```
function checkFileValidity(file) {
    return new Promise((resolve) => {
        if (file.size < 1000) {
            return resolve();
        }

        throw new Error("The uploaded file is too big");
    });
}

return (

);
```

Translations
--------------------------------------------------------------------------------------------

If you would like to use the components in your own language, you can pass a `translations` prop to the component.

```
translations = {
    fileTypeNotAllowed: "You must upload a file of type",
    tooLarge: "File too large, max",
    tooSmall: "File too small, min",
    tryAgain: "please try uploading this file again",
    somethingWentWrong: "Something went wrong while uploading this file",
    selectOrDrag: "Select or drag files",
    selectOrDragMax: "Select or drag max {maxItems} {file}",
    file: { singular: "file", plural: "files" },
    anyImage: "any image",
    anyVideo: "any video",
    goBack: "Go back",
    dropFile: "Drop file to upload",
    dragHere: "Drag file here",
    remove: "Remove",
    download: "Download",
};

return ;
```

The values mentioned here are the defaults. Feel free to only pass in a couple of keys, as your object will be merged onto the default.

If you use the component in different parts of your app, you might want to set the translations globally.

```
window.mediaLibraryTranslations = {
    somethingWentWrong: "whoops",
    remove: "delete",
};
```

Usage in Next.js
------------------------------------------------------------------------------------------------------

Because the components need references `document` and `window`, Server Side Rendering won't work. This means you'll have to use [dynamic imports](https://nextjs.org/docs/advanced-features/dynamic-import) to get the UI components to work.

```
import dynamic from "next/dynamic";
const MediaLibraryCollection = dynamic(
    () => import("@spatie/media-library-pro-react-collection"),
    { ssr: false }
);
```

Props
-----------------------------------------------------------------------

These props are available on both the `attachment` and the `collection` component.

prop nameDefault valueDescriptionnameinitialValue`[]`routePrefix`"media-library-pro"`uploadDomainUse this if you're uploading your files to a separate (sub)domain, e.g. `files.mydomain.com` (leave out the trailing slash)validationRulesRefer to the ["validation rules"](#validation-rules) sectionvalidationErrorsThe standard Laravel validation error objectmultiple`false` (always `true` in the `collection` component)Only exists on the `attachment` componentsmaxItems`1` when `multiple` = `false`, otherwise `undefinedvaporSet to true if you will deploy your application to Vapor, this enables uploading of the files to S3. [Read more](#usage-with-laravel-vapor)vaporSignedStorageUrl`"vapor/signed-storage-url"`maxSizeForPreviewInBytes`5242880` (5 MB)When an image is added, the component will try to generate a local preview for it. This is done on the main thread, and can freeze the component and/or page for very large filessortable`true`Only exists on the `collection` components. Allows the user to drag images to change their order, this will be reflected by a zero-based `order` attribute in the valuetranslationsRefer to the ["Translations"](#translations) sectionfileTypeHelpTextOverride the automatically generated helptext from `validationRules.accept`setMediaLibraryUsed to set a reference to the MediaLibrary instance, so you can change the internal state of the component.beforeUploadA method that is run right before a temporary upload is started. You can throw an `Error` from this function with a custom validation messageafterUploadA method that is run right after a temporary upload has completed, `{ success: true, uuid }`onChangeonIsReadyToSubmitChangeRefer to the ["Checking the upload state"](#checking-the-upload-state) section
