이미지 추가하기
// 실제로는 +의 plus_box를 클릭, 동작은 input의 type=[file] 속성을 사용, 이때 input은 보이지 않게 display none 처리.
// input[type=file]은 브라우저에서 직접 로컬 파일을 선택할 수 있게 해준다.
<input className='input_image' type='file' ref={inputRef} onChange={(event)=>{
if(event.target.files?.[0]) {
const reader = new FileReader()
const file = event.target.files?.[0];
reader.readAsDataURL(file)
reader.onloadend = event => {
setImageList(prev => [...prev, event.target?.result as string])
}
}
}} />
{
imaegList.map(img => <ImageBox key={img} src={img}/>)
}
<div className='plus_box' onClick={()=>{
inputRef.current?.click()
}>
+
</div>
File API
- FileList: 파일 리스트
- File: 파일 데이터
- FileReader: 파일 읽기
- Blob: 바이트 데이터
File Reader
- FileReader는 File이나 Blob의 내용을 읽을 수 있게 도와준다.
- FileReader를 사용하지 않는 이미지의 Local path는 fake path 이므로 사용했다.
- FileReader에는 4가지 방법으로 파일을 전달할 수 있다.
- readAsArrayBuffer(file|blob) [ArrayBuffer]
- readAsBinaryString(file|blob) [0..255 범위의 문자열]
- readAsDataURL(file|blob) [Base64]
- readAsText(file|blob) [UTF-16|UTF-8 문자열]
- FileReader에서 전달 받은 파일을 읽기 성공하면 load EventListner에 등록한 함수가 호출된다.
- 읽는 상태에 따라 loadstart | progress | loadend | error로 함수 호출
이미지 드래그하기
import {useDropzone} from 'react-dropzone'
import React, { useRef, useState, useCallback } from 'react';
import './App.css';
import ImageBox from './components/ImageBox';
function App() {
const inputRef = useRef<HTMLInputElement>(null)
const [imaegList, setImageList] = useState<string[]>([])
const onDrop = useCallback((acceptedFiles:any) => {
for(const file of acceptedFiles){
const reader = new FileReader()
reader.readAsDataURL(file)
reader.onloadend = event => {
setImageList(prev => [...prev, event.target?.result as string])
}
}
}, [])
const {getRootProps, getInputProps, open} = useDropzone({onDrop})
return (
<div className='container'>
// UX에 용이하도록 드래그 되는 범위를 전체로 설정
<div {...getRootProps()}>
<input {...getInputProps()} />
<div className={`wrapper_box ${imaegList.length > 0 ? 'row' : '' }`}>
{
imaegList.length === 0 &&
<div className='text'>
이미지가 없습니다. <br />
이미지를 추가해주세요.
</div>
}
{
imaegList.map((img,idx) => <ImageBox key={img+idx} src={img}/>)
}
<div className='plus_box' onClick={open}>
<input className='input_image' type='file' ref={inputRef} />
+
</div>
</div>
</div>
</div>
);
}
export default App;