Building an Image Gallery with Laravel and React

Today we are building an image gallery with Laravel and React. We are going to use react-dropzone to build an image uploader. react-dropzone is a  React’s implementation of popular drag and drop library for file uploading. On the backend, we are going to use Laravel’s Storage API to store images. 

Getting Started

Let’s start by creating a new Laravel project and change default scaffolding to React. Run these commands.

Database and Migrations

Populate .env file with your database credentials and run this command to create model and migration for photos table.

php artisan make:model Photos --migration

Add this code to your migration.

We are storing user_id of uploader along with image URI, height, and width of uploaded images on photos table. Later on, when building frontend gallery, we’ll pass height and width of images to react-photo-gallery which automatically calculates aspect ratio to generate a responsive image layout. After storing uploaded file, we’ll store its local path in URI column.

Also, update your Photos model and add these columns to $fillable array to avoid mass assignment exception.

Installing Dependencies

Before moving on to the Frontend part, install these dependencies.

We are using react-router  v4 with React for routing.

Bootstrapping React App

Add app.blade.php  file to views folder and add this HTML scaffolding to it.

Now add an all requests route to render this view against all incoming requests.

We’ve added all requests route under an auth route group to ensure authenticated access to our single page application. Create GalleryController and add index method to it.

php artisan make:controller GalleryController

React App

Now that we’ve configured our application routes to serve our SPA, we can start writing our React app. Let’s start by wrapping our application’s Root component inside a BrowserRouter. resources/assets/js/app.js is our applications entry point.

Now create a Root.js file under resources/assets/js/components directory and add this code.

We are rendering four subcomponents under our Root component,  NavbarGallery, ManageGallery, and  Uploader.

Navigation

To allow users to navigate between components, we are rendering our Navbar component at the top. Navbar component is visible on all routes.

We are using render prop instead of component on Route to allow it to pass down its props to Navbar component. We are using location pathname from props to assign an active class to our navigation links. This is how it looks like.

Image Uploader

Now create Uploader.js file under components directory and add this code.

In our Uploader component, we’re rendering a dropzone button, an upload button, bootstrap progress, a div to display accepted images and a message in case no images are selected. We’ve added two function callback as props to dropzone which will be called after selected images are accepted or rejected. Lets define these methods to handle these callbacks.

dropzone automatically validates files by mime type. We’re passing an array of acceptable mime type strings as accept prop to Dropzone component. On successful selection, we’ll add selected files to images state. On rejection, we’ll show a toastr error with invalid file upload error. We’ll show upload button if images exist on images state.

Now let’s implement upload button onClick handler.

We are separately uploading every accepted file. After successfully upload, we’ll remove the file from state and update the progress bar. Add these routes to your app to handle file requests.

Add uploadPhotos method to your GalleryController to upload files.

In this method, we are retrieving the uploaded file and its extension and generate a unique name by concatenating file extension with a random string. We are then calculating image height and width with getimagesize() method. After storing file to public disk using Laravel’s Storage facade, we’re creating a new post on posts table with URI of uploaded image. After a successful upload, we’ll remove the file from Uploader component state. Our file uploader looks like this.

To remove any selected images from the uploader, we also need to define a  removeDroppedFile method.

We’re rendering a remove button along without our images. When pressed, we’ll simply remove the selected image from the Uploader component state.

Image Gallery

We’ll display uploaded images in our Gallery component. Add Gallery.js file to components directory.

Add getPhotos() method to our GalleryController to handle our /posts GET request.

We are returning a JSON response with all images uploaded by the user. After getting a response, we are updating images state on Gallery component. We are using  react-photo-gallery to render images and  react-images Lightbox to display them in the overlay. We’re defining a few event handlers for Lightbox to handle close, next and previous events.

On click, Lightbox overlay will be displayed.

Managing Uploads

We have a separate component to manage uploaded images. ManageGallery has the same layout as Gallery component. The only difference is that it doesn’t display Lightbox overlay on click events. Instead, it lets you select images on click and delete them. Add ManageGallery component.

In our ManageGallery component, we’ll mark the image as selected on click event. If there are marked images, we’ll display a delete button. Add this method to handle onClick events.

After updating state, we are calling verifyMarked in which we’ll calculate the total number of marked images and update selected and state on our component.

To handle delete button on click event, add this method.

We are filtering out marked images and then requesting DELETE /posts route to delete the image from database and storage. Add this method to your GalleryController to handle this request.

After deleting the file from public storage, we’ll remove the record from the database and return a success response. On the frontend, we’ll remove deleted images from components local state.

Here’s a working demo of our app. If you’ve been following this tutorial from the start, you should be able to implement it without any problem. Still, if you’ve any issue or questions, please leave a comment and I’ll try to help. Here’s a Github repository link. Clone and run  npm install && npm run watch to give it a try.

 

Share this post

8 thoughts on “Building an Image Gallery with Laravel and React”

  1. Your tutorials are fantastic! My thanks for taking the time to create and publish them to your blog for us. The only problem with this one I had was the instructions are missing the removeDroppedFile method in the Uploader component, which causes an error when you “select images”.
    Again thank you so much. I hope you keep writing these.

    1. Thank you for pointing that out. I’ve updated the tutorial. Sometimes I omit few details in my tutorials. In such cases, please check linked GitHub repositories for complete code.

  2. Thanks for such a wonderful insight into the topic. Meanwhile, can you please let me know how do I serve the image data to the user. Complete sharing of the project would help.
    Regards

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.