[리액트] 이미지 미리보기, 업로드

임승민·2022년 10월 3일
0

React 기능구현

목록 보기
2/6
post-thumbnail

전체 코드

css속성을 뺀 전체적인 코드는 아래와 같으며 순서대로 설명하겠다.

import React, { useRef, useState } from "react";
import styled from "styled-components";

export default function App() {
  const [accountImg, setAccountImg] = useState("");
  const imgRef = useRef();

  const imgChangeHandler = () => {
    const reader = new FileReader();
    reader.readAsDataURL(imgRef.current.files[0]);
    reader.onloadend = () => {
      setAccountImg(reader.result);
    };
  };

  return (
      <AccountImageWrap>

        <AccountImageFile userImgUrl={accountImg} />
        <AccountImageInput
          type="file"
          accept="image/*"
          id="imgChangeBtn"
          ref={imgRef}
          onChange={() => imgChangeHandler()}
        />
        <AccountImageChangeBtn htmlFor="imgChangeBtn"> /*<- <label>태그*/
          사진 변경
        </AccountImageChangeBtn>

      </AccountImageWrap>
  );
}

1. 사진 선택

<AccountImageInput
  type="file"
  accept="image/*"
  id="imgChangeBtn"
  ref={imgRef}
  onChange={() => imgChangeHandler()}
/>
  1. type=”file“의 input태그를 만든다.
  2. accept=”image/*” 로 이미지 파일만 선택되게 설정한다.
    또 아래처럼 선택한 확장자만 선택할 수 있게 제어할 수 있다.
    accept="image/png, image/jpeg "
  3. id, ref는 추후에 설명하겠다.
  4. onChange이벤트로 사진을 선택하면 함수가 실행되게 한다.(바로 다음 설명 예정)

2. 이미지 출력하기

const [accountImg, setAccountImg] = useState("");
const imgRef = useRef(); 

const imgChangeHandler = () => {
    const reader = new FileReader();
    reader.readAsDataURL(imgRef.current.files[0]);
    reader.onload = () => {
      setAccountImg(reader.result);
    };
  };

input태그에 onChange이벤트가 실행되면 위의 함수가 실행된다.

  • DOM접근
  1. useRef를 선언한 뒤 imgRef변수에 할당한다.
  2. input에 ref값으로 imgRef를 넣어서 DOM에 접근한다.
    <AccountImageInput ref={imgRef}/>
  3. imgRef.current.files[0] 로 이미지 정보가 담긴 객체를 반환할 수 있다.
  • 이미지 출력
  1. FileReader를 선언한 뒤 reader에 할당한다.
  2. readAsDataURL 메소드 인자에 이미지 정보를 담은 객체(imgRef.current.files[0])를 넣어준다.
  3. 그럼 reader.result로 base64(64진법) 문자열이 반환된다.
  4. onloadend 이벤트로 읽기가 끝나면 state값을 reader.result로 set한다.
  5. accountImg(reader.result)를 img의 src, background-img의 url에 넣으면 이미지가 출력 된다.
const AccountImageFile = styled.div`
  background-image: url(${(props) => props.userImgUrl});
`;

3. 버튼 만들기

type=”file“의 input은 버튼을 디자인 할 수 없고, value도 설정할 수 없다.

따라서 label 태그를 이용해 버튼 역할을 하게 만들 것이다.

  1. label태그를 선언하고 htmlFor의 값으로 input의 id 값을 넣어준다.
  2. input과 label 2개의 버튼이 생긴다.
  3. input의 버튼은 더 이상 필요 없기 때문에 display=none;을 해준다.
<AccountImageChangeBtn htmlFor="imgChangeBtn"> {/*<label>태그*/}
  사진 변경
</AccountImageChangeBtn>

+ 이미지 업로드

이미지를 업로드 하려면 서버로 이미지를 전송해야 하는데 이 때 FormData로 보내야 서버에 이미지 파일을 보낼 수 있다. 서버에서 FormData를 받으면 이미지 URL을 만들어서 돌려준다.

const formData = new FormData();
  formData.append("file", imgRef.current.files[0]);
  UsersAPI.changeUserImg(formData)
  1. FormData를 선언하고 변수에 할당한다.
  2. append메소드로 첫번째 인자는 key, 두번째 인자는 value로 데이터를 추가한다.
  3. 변수인 formData를 body에 담아 서버로 전송한다.

0개의 댓글