Upload multiple images To Rails 7 API - Active_storage : Part 2
Published: 2023-03-13 10:37:08

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9n801go8bw49d4l3myg4.PNG)
---
Uploading multiple images is a common task when building web applications. 

In this blog post, we will go through the steps to upload multiple images to a backend API using React.js

This blog post is the part of our will be divided into 2 parts

**Part 1 :** Backend API whit Rails 7
- Github link : [multiple-image-uploads-api](https://github.com/Chrissiku/multiple-image-uploads-api)
- Blog post : [Part 1](https://dev.to/chrissiku/upload-multiple-images-to-rails-7-api-activestorage-2o6p)

**Part 2 :** Frontend with React.js
- Github link : [multiple-image-uploads-client](https://github.com/Chrissiku/multiple-image-uploads-client)

---


- First create a new react app bootstraped with vitejs
```sh
npm create vite@latest multiple-image-uploads-client
```
- Select `React` click enter, then `javascript` as shown on the images bellow

| React | JavaScript |
| -------- | -------- |
| ![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8fprbsf4bgfdt9fika31.PNG) | ![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y8im634lnsvxara3v6vc.PNG) |


- Navigate to the project and install all dependencies
```sh
cd multiple-image-uploads-client
npm install
```

- Go back to the [backend project](https://dev.to/chrissiku/upload-multiple-images-to-rails-7-api-activestorage-2o6p) and run the rails server again
```sh
rails server
```

- Now open the frontend in your prefered code editor and run server as well
```sh
npm run dev
```

At this point you should have 2 servers running on 2 differents ports.

 The backend on [http://127.0.0.1:3000/](http://127.0.0.1:3000/) and the frontend on [http://127.0.0.1:5173/](http://127.0.0.1:5173/)

- Clean up the `App.jsx` file in under `src/` directory and make it look like the following :

```js
import { useState } from "react";
import "./App.css";

function App() {
  return (
    <div className="App">
      Upload multiple images To Rails 7 API - Active_storage : Part 1
    </div>
  );
}

export default App;

```

- At this point we can start implementing all neccessary features.
copy and paste the following code into `App.jsx` file then read the explaination after.

```javascript
import { useState, useRef } from "react";
import "./App.css";

const API_URL = "http://127.0.0.1:3000";

function App() {
  const [images, setImages] = useState([]);
  const imagesRef = useRef(null);
  const postToGet = useRef("");

  const handleUpload = (e) => {
    e.preventDefault();
    const formData = new FormData();
    formData.append("post[title]", Date.now().toString());

    if (imagesRef.current && imagesRef.current.files) {
      for (let i = 0; i < imagesRef.current.files.length; i++) {
        formData.append("post[images][]", imagesRef.current.files[i]);
      }
      postData(formData);
    }
  };

  const postData = (formData) => {
    fetch(`${API_URL}/posts`, {
      method: "POST",
      body: formData,
    })
      .then((res) => res.json())
      .then((data) => {
        console.log(data);
        getImages(data.id);
      })
      .catch((err) => console.log(err));
  };

  const getImages = (postId) => {
    fetch(`${API_URL}/posts/${postId}`)
      .then((res) => res.json())
      .then((data) => {
        console.log(data);
        setImages(data.images || []);
      })
      .catch((err) => console.log(err));
  };

  return (
    <div className="App">
      {/* upload form */}
      <form style={{ margin: "10px" }}>
        <input
          type="file"
          name="image"
          multiple
          ref={imagesRef}
          style={{ margin: "5px" }}
        />
        <button type="button" onClick={handleUpload}>
          Submit
        </button>
      </form>
      {/* Get images button */}
      <div style={{ margin: "10px" }}>
        <input
          type="number"
          ref={postToGet}
          placeholder="ID to retrieve"
          style={{ margin: "5px" }}
        />
        <button onClick={() => getImages(postToGet.current.value)}>
          Get Images
        </button>
      </div>
      {/* images */}
      <div className="images">
        {images.map((image, index) => (
          <img
            key={index}
            src={image}
            alt="uploaded"
            style={{ width: "200px", height: "200px", margin: "10px" }}
          />
        ))}
      </div>
    </div>
  );
}

export default App;

```

## Explainations :

This is a React application that allows users to upload images and retrieve previously uploaded images by making API requests to a local server at `http://127.0.0.1:3000`.

The `useState` and `useRef` hooks are imported from the react module at the beginning of the file.

The `App` function is defined as the main component of the application. Inside the component, the state variable `images` is initialized to an empty array and the ref variable `imagesRef` is initialized to `null`. Another ref variable `postToGet` is initialized to an empty string.

The `handleUpload` function is defined to handle the form submission when the user uploads an image. The function first prevents the default form submission behavior by calling `preventDefault()` on the event object passed in as an argument. It then creates a new `FormData` object and appends the title of the post, which is set to the current timestamp as a string. The function then loops through the `files` property of the `imagesRef` ref variable and appends each file to the `FormData` object. Finally, the `postData` function is called with the `FormData` object as an argument.

The `postData` function sends a POST request to the server using the `fetch` API. It includes the `formData` object as the body of the request and sets the content type to `multipart/form-data`. When the response is received, it is converted to JSON using the `json()` method and the resulting data is logged to the console. The `getImages` function is then called with the `id` of the newly created post as an argument. If there is an error, it is caught and logged to the console.

The `getImages` function sends a GET request to the server to retrieve the images associated with a specific post ID. When the response is received, it is converted to JSON using the `json()` method and the resulting data is logged to the console. If the response includes an `images` property, the state variable `images` is updated with the array of images. If there is an error, it is caught and logged to the console.

The `return` statement of the `App` function includes a form for uploading images, a form for retrieving images by post ID, and a section for displaying the images. The form for uploading images includes an `input` element of type `file` with the `imagesRef` ref variable attached to it, and a `button` element with an `onClick` event listener attached to it that calls the `handleUpload` function. The form for retrieving images includes an `input` element of type `number` with the `postToGet` ref variable attached to it, and a `button` element with an `onClick` event listener attached to it that calls the `getImages` function with the value of the `postToGet` ref variable as an argument. The section for displaying images includes an array of `img` elements, each with a unique `key` attribute, a `src` attribute set to the URL of the image, and styling to set the dimensions and margin. The `images` state variable is mapped over to create the array of img elements.

Finally, the `App` component is exported as the default export of the module, allowing it to be used in other parts of the application.

If you have any suggestions, please feel free to leave a comment and connect with me so that we can implement them together through pair-programming. Don't forget to follow, like, and share.


## [⏮⏮ part 1 ](https://dev.to/chrissiku/upload-multiple-images-to-rails-7-api-activestorage-2o6p)