[Codecamp-Week4] useRef

·2022년 7월 28일
0

React에는 다양한 Hook이 있다.
Hook 중 하나인 useRef에 대해 알아보자!

1. useRef 란?

useRef란 useState처럼 React Hook 중 하나로, HTML 태그를 변수에 저장하도록 도와주는 역할을 한다.
따라서 focus를 선택하거나 하나의 태그를 다른 태그로 대체하는 등의 상황에 활용할 수 있다.

2. useRef 살펴보기

useRef를 사용하기 위해서는 (1) useState처럼 import를 해주고, (2) 변수에 저장하고 싶은 HTML 태그에 ref={변수} 를 작성해준다.

1) useEffect와 함께 useRef 살펴보기 : 커서 깜빡이기

input 태그를 inputRef에 저장해주기 위해 ref={inputRef}를 작성해주었으며,
커서 깜빡임 효과를 주기 위해 useEffect를 활용하여 inputRef.current.focus()를 넣어주었다.
(useEffect에 대해서는 다음 블로그 글에서 살펴보자!)

import { useEffect, useRef } from "react";

export default function useRefPage() {
  const inputRef = useRef<HTMLInputElement>(null);

  useEffect(() => {
    inputRef.current?.focus();
  });

  return <input type="password" ref={inputRef}></input>;
}

2) file input 버튼 숨기고 새로운 버튼으로 해당 기능 대체하기

file input 버튼은 꽤 못생겼다 (?)
그 버튼을 대체하는 예쁜 버튼을 활용하기 위해서는 기존 input 버튼은 숨기고 해당 역할을 대신 해주는 버튼을 만들어줘야한다.

Apollo client를 활용하여 파일 업로드 API를 연결해주었고,
file input에 등록하는 사진을 useState를 활용하여 상자에 담아준 후 onChange에 활용하였다.
못생긴 file input을 숨기기 위해 style에 display: "none"을 주었고,
이미지 선택 div를 대신 활용하기 위해 file input에 ref={fileRef}를 준 후 이미지 선택 div에 onClick을 활용하여 file input을 대체했다.

import { gql, useMutation } from "@apollo/client";
import { Modal } from "antd";
import { ChangeEvent, useRef, useState } from "react";
import { checkValidationFile } from "../../src/commons/libraries/validationFile";
import {
  IMutation,
  IMutationUploadFileArgs,
} from "../../src/commons/types/generated/types";

const UPLOAD_FILE = gql`
  mutation uploadFile($file: Upload!) {
    uploadFile(file: $file) {
      url
    }
  }
`;

export default function ImageUploadPage() {
  const fileRef = useRef<HTMLInputElement>(null);

  const [imageUrl, setImageUrl] = useState("");

  const [uploadFile] = useMutation<
    Pick<IMutation, "uploadFile">,
    IMutationUploadFileArgs
  >(UPLOAD_FILE);

  const onChangeFile = async (event: ChangeEvent<HTMLInputElement>) => {
    const file = event.target.files?.[0];
    console.log(file);

    const isValid = checkValidationFile(file);
    if (!isValid) return;

    try {
      const result = await uploadFile({ variables: { file } });
      console.log(result.data?.uploadFile.url);
      setImageUrl(result.data?.uploadFile.url || "");
    } catch (error) {
      Modal.error({ content: "에러발생!" });
    }
  };

  const onClickImage = () => {
    // 파일 태그(fileRef 변수)를 클릭해줘
    fileRef.current?.click();
  };

  return (
    <>
      <div
        style={{ width: "50px", height: "50px", backgroundColor: "gray" }}
        onClick={onClickImage}
      >
        이미지 선택
      </div>
      <input
        style={{ display: "none" }}
        type="file"
        onChange={onChangeFile}
        ref={fileRef}
        // 선택 가능한 파일 확장자 제한
        accept="image/jpeg"
      ></input>
      <img src={`https://storage.googleapis.com/${imageUrl}`}></img>
    </>
  );
}
profile
개발을 개발새발 열심히➰🐶

0개의 댓글