Meme's IT

[React] 파일 업로드 버튼 만들기(+ typescript) 본문

FrontEnd/React

[React] 파일 업로드 버튼 만들기(+ typescript)

Memez 2024. 3. 12. 17:00

기본 세팅 : typescript, react

 

 

기본적으로는 input 태그 사용

<input type="file" style={{display:'none'}}/>

이런식으로 안보이는 input 태그 생성

 

그러고 나서 react의 useRef를 이용해서

const fileInput = useRef<HTMLInputElement>(null);

이런식으로 다룰 변수를 하나 만들어줌

 

 

그리고 file을 저장하기 위해 useState를 써서

const [file, setFile] = useState<File|null>(null)

file 변수도 생성

 

버튼이 눌리면 → 파일 선택이 되도록하기 위해서 버튼 하나 생성 후 onClick 걸어줌

<button onClick={() => {fileInput.current?.click()}}>
  <p className="underline ml-1 hover:text-violet-500 hover:cursor-pointer">업로드하기</p>
</button>

p태그 스타일은 tailwind CSS라 무시가능

 

그 다음에 input 태그에

<input type="file" ref={fileInput} onChange={handleChange} style={{display:'none'}}/>

fileInput을 ref로, onChange함수를 만들어서 걸어주자

handleChange 함수는

const handleChange = (event :React.ChangeEvent<HTMLInputElement>) => {
  // 선택한 파일 정보를 저장
  const files = event.target.files
  if (files && files[0]) {
    setFile(files[0])
  }
};

업로드된 함수를 file변수에 넣어준다

 

그리고, 이걸 저장하거나 axios로 보내주려면 file이 바뀐다면 useEffect로 보내주자

useEffect(()=> {
    if (file != null) {
      // 여기에 axios 요청
    }
  }, [file])

나는 SweetAlert를 이용해서

useEffect(()=> {
    if (file != null) {
      console.log(file)
      Swal.fire({
        title: '업로드완료',
        icon: "success"
      }).then((r) => {goNext()})
    }
  }, [file])

이런식으로 했음

 

 

마지막으로 파일 형식을 png만 받고 싶다면?

<input type="file" accept=".png" ref={fileInput} onChange={handleChange} style={{display:'none'}}/>

accept='.png'로 제한 걸어주자

 

 


전체 코드

function House0({ goNext }: propsType) {
  const [file, setFile] = useState<File|null>(null)
  const fileInput = useRef<HTMLInputElement>(null);
  const handleChange = (event :React.ChangeEvent<HTMLInputElement>) => {
    // 선택한 파일 정보를 저장
    const files = event.target.files
    if (files && files[0]) {
      setFile(files[0])
    }
  };

  // 써먹을려면
  useEffect(()=> {
    if (file != null) {
      console.log(file)
      Swal.fire({
        title: '업로드완료',
        icon: "success"
      }).then((r) => {goNext()})
    }
  }, [file])

  return (
    <div className="flex h-svh w-svh justify-center items-center flex-col">
      <p className="text-center mb-8 font-bold text-3xl">집을 그려주세요.</p>
      <div className="relative border-2 rounded h-2/3 w-5/6">
        <Draw />
        <Button className="absolute bottom-0 right-0 m-3" onClick={goNext}>다 그렸어요</Button>
      </div>
      <div className="flex items-center text-slate-500 mt-2">
        <p className="mr-3">그리기 힘들다면?</p>
        {/* 업로드 아이콘 */}
        <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="w-6 h-6">
          <path strokeLinecap="round" strokeLinejoin="round" d="M12 16.5V9.75m0 0 3 3m-3-3-3 3M6.75 19.5a4.5 4.5 0 0 1-1.41-8.775 5.25 5.25 0 0 1 10.233-2.33 3 3 0 0 1 3.758 3.848A3.752 3.752 0 0 1 18 19.5H6.75Z" />
        </svg>
        <button onClick={() => {fileInput.current?.click()}}>
          <p className="underline ml-1 hover:text-violet-500 hover:cursor-pointer">업로드하기</p>
        </button>
      </div>
      {/* png형식의 파일만 올릴 수 있도록 함 */}
      <input type="file" accept=".png" ref={fileInput} onChange={handleChange} style={{display:'none'}}/>
    </div>
  )
}