Upload multiple images To Rails 7 API - Active_storage : Part 2

chrissiku

Chris Siku

Posted on March 13, 2023

Upload multiple images To Rails 7 API - Active_storage : Part 2

Image description

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

Part 2 : Frontend with React.js


  • First create a new react app bootstraped with vitejs
npm create vite@latest multiple-image-uploads-client
Enter fullscreen mode Exit fullscreen mode
  • Select React click enter, then javascript as shown on the images bellow
React JavaScript
Image description Image description
  • Navigate to the project and install all dependencies
cd multiple-image-uploads-client
npm install
Enter fullscreen mode Exit fullscreen mode
rails server
Enter fullscreen mode Exit fullscreen mode
  • Now open the frontend in your prefered code editor and run server as well
npm run dev
Enter fullscreen mode Exit fullscreen mode

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

The backend on http://127.0.0.1:3000/ and the frontend on http://127.0.0.1:5173/

  • Clean up the App.jsx file in under src/ directory and make it look like the following :
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;

Enter fullscreen mode Exit fullscreen mode
  • 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.
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;

Enter fullscreen mode Exit fullscreen mode

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

💖 💪 🙅 🚩
chrissiku
Chris Siku

Posted on March 13, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related