Next.js - 이미지 업로드, 미리보기

윤스타·2024년 6월 12일

Next.js

목록 보기
1/9
post-thumbnail

Next.js 이미지 업로드, 미리보기

1개의 이미지만 업로드 할 경우

FileReader( )

  • javascript의 FileReader를 사용한다.
"use client"

import React, { useRef, useState } from "react";
import styles from "./imagePicker.module.css";
import Image from "next/image";

export default function ImagePicker({ label, name }) {
  const [pickedImage, setPickedImage] = useState();
  const imageInput = useRef();

  function handlePickClick() {
    imageInput.current.click();
  }

  function handleImageChange(e) {
    const file = e.target.files[0];

    if (!file) {
      setPickedImage(null);
      return;
    }

    const fileReader = new FileReader();

    fileReader.onload = () => {
      setPickedImage(fileReader.result);
    };

    fileReader.readAsDataURL(file);
  }

  return (
    <div className={styles.picker}>
      <label htmlFor={name}>{label}</label>
      <div className={styles.controls}>
        <div className={styles.preview}>
          {!pickedImage && <p>No image picked yet.</p>}
          {pickedImage && (
            <Image
              src={pickedImage}
              alt="The image selected by the user"
              fill
            />
          )}
        </div>
        <input
          className={styles.input}
          type="file"
          id={name}
          accept="image/png, image/jpeg"
          name={name}
          ref={imageInput}
          onChange={handleImageChange}
          required
        />
        <button
          className={styles.button}
          type="button"
          onClick={handlePickClick}
        >
          Pick an Image
        </button>
      </div>
    </div>
  );
}

여러개의 이미지를 업로드 할 경우

  • const [pickedImages, setPickedImages] = useState([ ]);를 사용하여 여러 이미지를 저장할 수 있도록 상태를 배열로 수정한다.

  • 이미지 파일 읽기 : handleImageChange 함수에서 e.target.files를 Array.from으로 배열로 변환하고, 각각의 파일을 읽도록 수정한다.
    각 파일을 FileReader를 사용하여 읽고, 모든 파일이 로드되면 상태를 업데이트한다.

  • 미리보기 렌더링 : 여러 이미지를 렌더링하기 위해 pickedImages.map을 사용하여 각 이미지를 <div key={index} className={styles.previewImage}>로 감싸서 렌더링한다.

  • multiple 속성 추가: <input> 요소에 multiple 속성을 추가하여 여러 파일을 선택할 수 있도록 수정한다.

"use client";

import React, { useRef, useState } from "react";
import styles from "./imagePicker.module.css";
import Image from "next/image";

export default function ImagePicker({ label, name }) {
  const [pickedImages, setPickedImages] = useState([]);
  const imageInput = useRef();

  function handlePickClick() {
    imageInput.current.click();
  }

  function handleImageChange(e) {
    const files = Array.from(e.target.files);

    if (!files.length) {
      setPickedImages([]);
      return;
    }

    const newImages = [];
    const fileReaders = [];

    files.forEach((file, index) => {
      const fileReader = new FileReader();

      fileReaders.push(fileReader);

      fileReader.onload = () => {
        newImages.push(fileReader.result);
        if (newImages.length === files.length) {
          setPickedImages(newImages);
        }
      };

      fileReader.readAsDataURL(file);
    });
  }

  return (
    <div className={styles.picker}>
      <label htmlFor={name}>{label}</label>
      <div className={styles.controls}>
          {pickedImages.length === 0 && <p>No images picked yet.</p>}
          {pickedImages.map((image, index) => (
            <div key={index} className={styles.preview}>
              <Image
                src={image}
                alt={`Selected image ${index + 1}`}
                layout="fill"
                objectFit="cover"
              />
            </div>
          ))}
        <input
          className={styles.input}
          type="file"
          id={name}
          accept="image/png, image/jpeg"
          name={name}
          ref={imageInput}
          onChange={handleImageChange}
          multiple
          required
        />
        <button
          className={styles.button}
          type="button"
          onClick={handlePickClick}
        >
          Pick Images
        </button>
      </div>
    </div>
  );
}
profile
사이버 노트

0개의 댓글