ReactJS와 FileReader()
API를 사용하여 서버에 업로드하기 전에 브라우저에서 여러 이미지를 미리 보려고합니다 . 내가 가진 문제는 미리보기를 위해 일부 이미지를 선택할 때마다 마지막 이미지 만 표시된다는 것입니다.
내 코드는 다음과 같습니다.
class App extends Component {
constructor(props){
super(props);
this.state = {
id: "upload-photo",
imageURI: null
}
}
buildImgTag(){
let imgTag = null;
if (this.state.imageURI !== null) {
imgTag = (
<div className="photo-container">
<img className="photo-uploaded" src={this.state.imageURI} alt="Photo uploaded"/>
</div>
);
return imgTag;
}
}
readURI(e){
if (e.target.files) {
let filesAmount = e.target.files.length;
let i;
for (i = 0; i < filesAmount; i++) {
let reader = new FileReader();
reader.onload = function(ev) {
this.setState (
{
imageURI: ev.target.result
}
)
}.bind(this);
reader.readAsDataURL(e.target.files[i]);
}
}
}
handleChange(e){
this.readURI(e);
if (this.props.onChange !== undefined) {
this.props.onChange(e);
}
}
render() {
const imgTag = this.buildImgTag();
return (
<div className="container">
<div className="row justify-content-center">
<div className="col-md-6">
<div className="card">
<div className="card-header" style={{backgroundColor: 'rgb(232, 245, 253)', borderTopLeftRadius: '4px', borderTopRightRadius: '4px', display: 'flex', maxHeight: '50vh', minHeight: '25vh', overflow: 'hidden'}}>
<div className="avatar">
<img src="http://laratweet.local:8080/images/avatar-default.png" alt="User Avatar" className="user-avatar"/>
</div>
<div id="textEditor">
<form method="post" action="" encType="multipart/form-data">
<textarea name="" id="richTextArea" placeholder="What's happening?"></textarea>
{imgTag}
<div id="theRibbon">
<div>
<input
id={this.state.id}
type="file"
name=""
accept="image/gif,image/jpeg,image/jpg,image/png,video/mp4,video/x-m4v"
title="Add photos or video"
onChange={this.handleChange.bind(this)}
multiple
/>
<label htmlFor={this.state.id}>
<figure>
<svg xmlns="http://www.w3.org/2000/svg" width="30" height="27"
viewBox="0 0 20 17" className="upload-icon">
<path
d="M10 0l-5.2 4.9h3.3v5.1h3.8v-5.1h3.3l-5.2-4.9zm9.3 11.5l-3.2-2.1h-2l3.4 2.6h-3.5c-.1 0-.2.1-.2.1l-.8 2.3h-6l-.8-2.2c-.1-.1-.1-.2-.2-.2h-3.6l3.4-2.6h-2l-3.2 2.1c-.4.3-.7 1-.6 1.5l.6 3.1c.1.5.7.9 1.2.9h16.3c.6 0 1.1-.4 1.3-.9l.6-3.1c.1-.5-.2-1.2-.7-1.5z"/>
</svg>
</figure>
<span className="tooltiptext">Add photos or video</span>
</label>
</div>
<button type="submit" className="tweet">Tweet</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
}
선택한 모든 이미지가 브라우저에 표시 / 미리보기를 기대하지만 마지막 이미지 만 미리보기됩니다. 내가 도대체 뭘 잘못하고있는 겁니까?
여기서 주된 문제는 App
구성 요소 상태가 현재 하나만 추적 할 수 있다는 것 imageURI
입니다. state
의 배열을 imageURI
저장하고 렌더링 할 수 있도록 모델을 수정하는 것이 좋습니다.
this.state = {
id: "upload-photo",
imageArray: [] /* Replace imageURI with an array for multiple images */
}
다음으로 readURI()
구성 요소 상태에 여러 이미지를 저장 하도록 업데이트해야합니다 . 한 가지 방법은 Promise.all()
이미지 배열을 비동기 적으로로드하는 데 사용 하는 것입니다 .
readURI(e){
if (e.target.files) {
/* Get files in array form */
const files = Array.from(e.target.files);
/* Map each file to a promise that resolves to an array of image URI's */
Promise.all(files.map(file => {
return (new Promise((resolve,reject) => {
const reader = new FileReader();
reader.addEventListener('load', (ev) => {
resolve(ev.target.result);
});
reader.addEventListener('error', reject);
reader.readAsDataURL(file);
}));
}))
.then(images => {
/* Once all promises are resolved, update state with image URI array */
this.setState({ imageArray : images })
}, error => {
console.error(error);
});
}
}
마지막으로 buildImgTag()
여러 이미지가 렌더링되도록 업데이트 하기 만하면 됩니다. 이에 대한 한 가지 접근 방식은 다음과 같습니다.
buildImgTag(){
return <div className="photo-container">
{
this.state.imageArray.map(imageURI =>
(<img className="photo-uploaded" src={imageURI} alt="Photo uploaded"/>))
}
</div>
}
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다