How to Upload Multiple Images at Once in React

Banner for a MediaJam post

Christian Nwamba

Ever implemented an upload file feature with React and you try using an npm package but the package doesn’t have options for selecting multiple images? In this tutorial, we will solve that challenge by implementing a simple React app where users can select multiple images.

Prerequisites

  • Knowledge of JavaScript and React basics
  • Node >=v14 installed

The complete project is here on Codesandbox.

Getting Started

Let’s start by bootstrapping a new react project with create-react-app. Run the command below to do this:

1#bash
2npx create-react-app upload-multiple-images

When it’s done installing, run these commands in your terminal to start the React app.

1#bash
2cd upload-multiple-images
3npm run start

The app should start at http:localhost:3000.

Navigate to the src directory and delete all the files except index.js, App.js, and index.css. This would break the react app that’s running but don’t worry we’ll fix that soon.

Update the index.js with the code snippet below:

1//index.js
2import React from 'react';
3import ReactDOM from 'react-dom/client';
4import './index.css';
5import App from './App';
6
7const root = ReactDOM.createRoot(document.getElementById('root'));
8 root.render(
9 <React.StrictMode>
10 <App />
11 </React.StrictMode>
12 );

In this project, we’ll be using react-bootstrap components, so head to your terminal and run the following commands to install the packages.

1#bash
2npm install react-bootstrap bootstrap

If you’ve gotten up to this point, you’re awesome!

Creating Mock data

For this project, we’ll be using some mock images to demonstrate multiple selections. Go ahead and create a mock.js file at the root directory. Paste this code snippet in mock.js.

1//mock.js
2
3export const mockData = [
4 {
5 src: "https://images.unsplash.com/photo-1653325532801-20505a866e9d?crop=entropy&cs=tinysrgb&fm=jpg&ixlib=rb-1.2.1&q=80&raw_url=true&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=387",
6 },
7 {
8 src: "https://images.unsplash.com/photo-1534353436294-0dbd4bdac845?crop=entropy&cs=tinysrgb&fm=jpg&ixlib=rb-1.2.1&q=80&raw_url=true&ixid=MnwxMjA3fDF8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=387",
9 },
10 {
11 src: "https://images.unsplash.com/photo-1471897488648-5eae4ac6686b?crop=entropy&cs=tinysrgb&fm=jpg&ixlib=rb-1.2.1&q=80&raw_url=true&ixid=MnwxMjA3fDF8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=387",
12 },
13 {
14 src: "https://images.unsplash.com/photo-1653325297180-2ba1b7e34215?crop=entropy&cs=tinysrgb&fm=jpg&ixlib=rb-1.2.1&q=80&raw_url=true&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=379",
15 },
16 {
17 src: "https://images.unsplash.com/photo-1652534603944-2ebdf360d6c7?crop=entropy&cs=tinysrgb&fm=jpg&ixlib=rb-1.2.1&q=80&raw_url=true&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=725",
18 },
19 {
20 src: "https://images.unsplash.com/photo-1653349859617-48672bdfa490?crop=entropy&cs=tinysrgb&fm=jpg&ixlib=rb-1.2.1&q=80&raw_url=true&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=423",
21 },
22 {
23 src: "https://images.unsplash.com/photo-1653356677409-27ecda2dcba4?crop=entropy&cs=tinysrgb&fm=jpg&ixlib=rb-1.2.1&q=80&raw_url=true&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=387",
24 },
25 {
26 src: "https://images.unsplash.com/photo-1653359406652-843d58aec2c8?crop=entropy&cs=tinysrgb&fm=jpg&ixlib=rb-1.2.1&q=80&raw_url=true&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=387",
27 },
28 {
29 src: "https://images.unsplash.com/photo-1653376774810-a81964615abb?crop=entropy&cs=tinysrgb&fm=jpg&ixlib=rb-1.2.1&q=80&raw_url=true&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=391",
30 }
31]

Now we’ve created our mock data, let’s go ahead and make use of the data in our App component.

Implementing Component UI

Let’s create a simple image grid UI. Navigate to App.js and add the code snippet below:

1//App.js
2
3import 'bootstrap/dist/css/bootstrap.min.css';
4import { Container, Col, Row, Image } from 'react-bootstrap'
5import { mockData } from './mock';
6
7function App() {
8 const handleClick = () => { }
9return (
10 <Container>
11 <Row>
12 {mockData.map((data, index) => (
13 <Col md={4} key={index} >
14 <div className="img-card" onClick={() => handleClick(data.src)}>
15 <Image style={{ width: '300px', height: "300px" }} thumbnail src={data.src} />
16 </div>
17 </Col>
18 )
19 )}
20 </Row>
21 </Container>
22);
23}
24export default App;

Let’s break down the code snippet into chunks.

First, we import bootstrap css so we can use bootstrap styles with our react-bootstrap components. Next, we import react-bootstrap components, and we use them in the template. We also imported the mock data and used it in templates. There’s also a handleClick() function we’ll work on in the next section. Let’s also some custom css styles. Go to index.css and add these lines of code:

1//index.css
2
3body {
4 margin: 0;
5 font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
6 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
7 sans-serif;
8 -webkit-font-smoothing: antialiased;
9 -moz-osx-font-smoothing: grayscale;
10}
11
12.img-checked {
13 padding: 10px;
14 width: 300px;
15 background: rgb(49, 132, 199);
16 color: white;
17 border-radius: 20px;
18 font-weight: bolder;
19 position: relative;
20 /* margin-top: 2px ; */
21}
22.img-card{
23 border: 3px solid rgb(95, 95, 95);
24 margin: 10px;
25 width: 300px;
26}
27.img-card:hover {
28 border: 2px solid red;
29}

Run the app with npm run start and navigate to your browser. You should have something like this:

Awesome. Let’s now go ahead to implement select functionality.

Implementing Multiple Select Functionality

After displaying the image gallery, we will create a hover event for marking images that will be uploaded. Navigate to the App``.js file and update with the following lines of code.

1//App.js
2...
3import { useState } from 'react'
4...
5
6function App() {
7 const [allImages, setAllImages] = useState([]);
8 const handleClick = async (source) => {
9 const check = allImages.includes(source)
10 if (check) {
11 const id = allImages.indexOf(source)
12 let newArr = allImages
13 newArr.splice(id, 1)
14 setAllImages([...newArr])
15 } else {
16 allImages.push(sourc)
17 setAllImages([...allImages])
18 }
19 }
20
21return (
22 ...
23 <div className="img-card" onClick={() => handleClick(data.src)}>
24 ....
25 {allImages.includes(data.src) ?
26 <div className="img-checked" >Selected</div>
27 : null}
28 </div>
29)
30}

The above code snippets include some state variables.

  • allImages: This is an array of the selected images.
  • handleClick: This function handles the onClick event when adding an image to the list.

We wrapped our image tag with a div that has an on hover event, such that a border appears on hover. We then display a text selected when an image is selected.

We then implemented the handleClick function. The function handles the onClick event. It checks if the value passed exists in the mock**D**ata ****array; if so, it pops the value from the array. If not, it pushes the value into the array.

Go ahead save and run the app on your terminal. You should see something like this:

We can now upload the array of images to an external platform or an upload media API endpoint.

Conclusion

In this tutorial, we learned how to build a React application that handles multiple image uploads with React Bootstrap.

Christian Nwamba

Developer Advocate at AWS

A software engineer and developer advocate. I love to research and talk about web technologies and how to delight customers with them.