Many examples of this on here but can't seem to find any for react. I have managed to convert the vanilla js to react but getting an error.
The answer looks simple enough so here I go in react:
getInitialState: function(){
return{file: []}
},
_onChange: function(){
// Assuming only image
var file = this.refs.file.files[0];
var reader = new FileReader();
var url = reader.readAsDataURL(file);
console.log(url) // Would see a path?
// TODO: concat files for setState
},
render: function(){
return(
<div>
<form>
<input
ref="file"
type="file"
name="user[image]"
multiple="true"
onChange={this._onChange}/>
</form>
{/* Only show first image, for now. */}
<img src={this.state.file[0} />
</div>
)
};
Basically all answers I have seen show something like what I have. Any difference in React app?
Regarding answer:
The React app we are going to build has a file input. When you select an image with this file input, an image preview will show up below it. There is also a “Remove This Image” button that lets you remove the selected image and the preview as well.
To display a image selected from file input in React, we can call the URL. createObjectURL with the selected file object to and set the returned value as the value of the src prop of the img element. We define the img state which we use as the value of the src prop of the img element.
No difference, just read your image when the load
event finishes. After the load end
event handler just set your state:
getInitialState: function(){
return{file: []}
}
_onChange: function(){
// Assuming only image
var file = this.refs.file.files[0];
var reader = new FileReader();
var url = reader.readAsDataURL(file);
reader.onloadend = function (e) {
this.setState({
imgSrc: [reader.result];
})
}.bind(this);
console.log(url) // Would see a path?
// TODO: concat files
},
render: function(){
return(
<div>
<form>
<input
ref="file"
type="file"
name="user[image]"
multiple="true"
onChange={this_onChange}/>
</form>
{/* Only show first image, for now. */}
<img src={this.state.imgSrc} />
</div>
)
}
Extending on Cels' answer, and avoiding memory leaks with createObjectURL
as @El Anonimo warns about, we could use useEffect
to create the preview and clean up after the component unmounts like so
useEffect(() => {
// create the preview
const objectUrl = URL.createObjectURL(selectedFile)
setPreview(objectUrl)
// free memory when ever this component is unmounted
return () => URL.revokeObjectURL(objectUrl)
}, [selectedFile])
The full code could look something like this
export const ImageUpload = () => {
const [selectedFile, setSelectedFile] = useState()
const [preview, setPreview] = useState()
// create a preview as a side effect, whenever selected file is changed
useEffect(() => {
if (!selectedFile) {
setPreview(undefined)
return
}
const objectUrl = URL.createObjectURL(selectedFile)
setPreview(objectUrl)
// free memory when ever this component is unmounted
return () => URL.revokeObjectURL(objectUrl)
}, [selectedFile])
const onSelectFile = e => {
if (!e.target.files || e.target.files.length === 0) {
setSelectedFile(undefined)
return
}
// I've kept this example simple by using the first image instead of multiple
setSelectedFile(e.target.files[0])
}
return (
<div>
<input type='file' onChange={onSelectFile} />
{selectedFile && <img src={preview} /> }
</div>
)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With