Reputation: 3411
How come reader.onloadend does not execute? What i'm trying to do is store the src of the images uploaded and render a preview when I map through images array in the render method. What needs to change for file reader methods to actually execute?
import React, { Component } from 'react';
import { Button, Input } from 'semantic-ui-react';
class Uploadimage extends Component {
constructor(props) {
super(props);
this.state = {
file: '',
images:[],
};
}
setImages = (e) => {
e.preventDefault();
let { images } = this.state;
const imageFiles = document.getElementById("image");
const filesLength = imageFiles.files.length;
const temp = null;
let reader = new FileReader();
reader.onloadend = () => {
for(var i = 0; i < filesLength; i++) {
let file = e.target.files[i];
temp.push(reader.readAsDataURL(file));
}
this.setState({
images:temp
})
}
}
render() {
let { images } = this.state;
return (
<div>
<form onSubmit={this._handleSubmit}>
<Input id="image" type="file" multiple defaultValue='no file chosen' onChange={this.setImages} />
<Button icon='upload' type="submit" onClick={this._handleSubmit}>Upload Image</Button>
</form>
{images.map((item,index) => <img src={item} />)}
</div>
)
}
}
export default Uploadimage;
Upvotes: 1
Views: 8351
Reputation: 2664
I believe you'll have to move for
loop logic out of reader.onloadend
method
Until now I was under the impression that when using react, any form field can be turned into a controlled component, however fileUpload appears to be an exception
See updated code with comments below, I haven't tried this sorry:
class Uploadimage extends Component {
constructor(props) {
super(props);
this.state = {
file: '',
images:[],
};
this.fileReader = new FileReader();
}
setImages = (e) => {
e.preventDefault();
let self = this; // unsure if this is needed
self.setState({ images: [] }); // empty out current images array
const imageFiles = e.target.files; // document.getElementById("image"); // You may want to avoid querying the dom yourself, try and rely on react as much as possible
const filesLength = imageFiles.length; // imageFiles.files.length;
// const temp = null;
for(var i = 0; i < filesLength; i++) {
let reader = new FileReader();
let file = imageFiles[i];
reader.onloadend = () => {
self.setState({ images: self.state.images.concat(reader.result); });
}
reader.readAsDataURL(file);
}
}
render() {
let { images } = this.state;
return (
<div>
<form onSubmit={this._handleSubmit}>
<Input id="image" type="file" multiple defaultValue='no file chosen' onChange={this.setImages} />
<Button icon='upload' type="submit" onClick={this._handleSubmit}>Upload Image</Button>
</form>
{images.map((item,index) => <img src={item} />)}
</div>
)
}
}
Upvotes: 2
Reputation: 2153
There are couple of wrong things with your code:
reader.readAsDataURL(file)
is inside onloadend
callback - it should be outside, so the reader can read files and then call onloadend
after.temp
is null
and you try to use push
method. Set it to empty array.document.getElementById
in React - use refsUpvotes: 0