Skip to content

Instantly share code, notes, and snippets.

@hartzis
Last active April 3, 2023 18:09
Show Gist options
  • Save hartzis/0b77920380736f98e4f9 to your computer and use it in GitHub Desktop.
Save hartzis/0b77920380736f98e4f9 to your computer and use it in GitHub Desktop.
React Image Upload with Preview
// https://codepen.io/hartzis/pen/VvNGZP
class ImageUpload extends Component {
constructor(props) {
super(props);
this.state = {
file: '',
imagePreviewUrl: ''
};
this._handleImageChange = this._handleImageChange.bind(this);
this._handleSubmit = this._handleSubmit.bind(this);
}
_handleSubmit(e) {
e.preventDefault();
// TODO: do something with -> this.state.file
}
_handleImageChange(e) {
e.preventDefault();
let reader = new FileReader();
let file = e.target.files[0];
reader.onloadend = () => {
this.setState({
file: file,
imagePreviewUrl: reader.result
});
}
reader.readAsDataURL(file)
}
render() {
let {imagePreviewUrl} = this.state;
let $imagePreview = null;
if (imagePreviewUrl) {
$imagePreview = (<img src={imagePreviewUrl} />);
}
return (
<div>
<form onSubmit={this._handleSubmit}>
<input type="file" onChange={this._handleImageChange} />
<button type="submit" onClick={this._handleSubmit}>Upload Image</button>
</form>
{$imagePreview}
</div>
)
}
}
@quicksnap
Copy link

Nice snippet! Thanks.

@ch3rn4nq88
Copy link

Nice! many many thanks!

@BearandYoon
Copy link

Thanks a lot.

@johnfdhartman
Copy link

Really helpful, thanks!

@kingisaac95
Copy link

This was really helpful, thanks!

@adithyamaheshb
Copy link

Nice One!

@tetar998
Copy link

how can you transform this file into b64 file and upload it on a API ?

@ahmad-nasikin
Copy link

ahmad-nasikin commented Apr 13, 2018

@tetar998 handleSubmit () { const formData = new FormData() formData.append('image', this.state.file) axios.post('url', formData) .then(response => { console.log(response) }) }

@AbhishekRaval
Copy link

Works Like a Charm, thank you !

Copy link

ghost commented Jun 8, 2018

How would you edit the _handleImageChange function so we might preview multiple photos?

@juliusdejon
Copy link

Nice Component!. This will be better if you add a condition whether a file is selected on _handleImageChange. just add this
if (file) {
reader.readAsDataURL(file);
}

so it checks whether a file is selected or not
because it will produce error such as
TypeError: : Failed to execute 'readAsDataURL' on 'FileReader': parameter 1 is not of type

@jacksonmoji
Copy link

Great Component, it really saved me!! NB -- still a newbie in reactjs 💯

@Fats403
Copy link

Fats403 commented Jul 6, 2018

Awesome component, thanks man!

@Stanley-Yao
Copy link

Great!!! But one question, how to deal with the the state of multiple image upload preview? Should I put them in an array?

@nirmaldalmia
Copy link

How do you customize this component to only accept certain file extensions like '.jpg' or '.png'? New to React, would appreciate any help I can get.

@pranaydp27
Copy link

how can i add multiple images and preview them....?????

@Dangtrungphu
Copy link

can you help me how to add multiple images and preview pls?

@touhami92
Copy link

touhami92 commented Sep 24, 2018

this is cleaned version for react 16

import React, {Component} from 'react';


class ImageUpload extends Component {

    state = {
        file: '',
        imagePreviewUrl: ''
    };
  
    _handleSubmit = e => {
        e.preventDefault();
        // TODO: do something with -> this.state.file
    }
  
    _handleImageChange = e =>{
        e.preventDefault();
  
        let reader = new FileReader();
        let file = e.target.files[0];
        reader.onloadend = () => {
            this.setState({ file: file, imagePreviewUrl: reader.result });
        }
        reader.readAsDataURL(file)
    }
  
    render() {
        let {imagePreviewUrl} = this.state;
        let $imagePreview = null;
  
      return (
        <div>
            <form onSubmit={this._handleSubmit}>
                <input type="file" onChange={this._handleImageChange} />
                <button type="submit" onClick={this._handleSubmit}>Upload Image</button>
            </form>
            {!$imagePreview && <img src={imagePreviewUrl} />}
        </div>
      )
    }
  
}


export default ImageUpload;

@benoitkopp
Copy link

Hello guys, I just did it for multiple images, any remarks ?

import React from 'react';


class ImageUpload extends React.Component {
    state = {
        files: [],
        imagesPreviewUrls: []
    };

    _handleImageChange = e =>{
        e.preventDefault();

        // FileList to Array
        let files = Array.from(e.target.files);

        // File Reader for Each file and and update state arrays
        files.forEach((file, i) => {
            let reader = new FileReader();

            reader.onloadend = () => {
                this.setState(prevState => ({
                    files: [...prevState.files, file],
                    imagesPreviewUrls: [...prevState.imagesPreviewUrls, reader.result]
                }));
            }

            reader.readAsDataURL(file);
        });
    }

    render() {
        let {imagesPreviewUrls} = this.state;

        return (
            <div>
                <label className="btn btn-default btn-sm z-depth-0 mr-0 pl-2 pr-2 custom-file-upload waves-effect waves-light" htmlFor="file">
                    <i className="fas fa-image fa-fw" aria-hidden="true"></i>
                    <input className="upload" type="file" onChange={this._handleImageChange} multiple/>
                </label>
                {imagesPreviewUrls.map(function(imagePreviewUrl, i){
                    return <img key={i} src={imagePreviewUrl} />
                })}
            </div>
        )
    }
}


export default ImageUpload;

@akratzel
Copy link

If you are wondering how to only allow images to be uploaded, use this <input /> markup:
<input type='file' accept='image/*' />

@jdalegonzalez
Copy link

Thanks for the snippet. @touhami92 What am I missing with this code... {!$imagePreview && <img src={imagePreviewUrl} />}? Isn't $imagePreview always going to be null because of the set further up in the function? Isn't this effectively just: <img src={imagePreviewUrl} />?

@fbryo21
Copy link

fbryo21 commented Jun 1, 2019

How to insert it in database using php? Thanks.

@RafaaBelhedi
Copy link

Thanks dude <3

@bosskab123
Copy link

Thank you so much

@lamarrh
Copy link

lamarrh commented Apr 7, 2020

This was super useful for me, I also wrapped it in a react-awesome-slider for better display.

import AwesomeSlider from "react-awesome-slider";

{imagesPreviewUrls.length > 0 && (
          <AwesomeSlider>
            {imagesPreviewUrls.map(function (imagePreviewUrl, i) {
              return (
                <div>
                  <img style={style} key={i} src={imagePreviewUrl} alt="" />
                </div>
              );
            })}
          </AwesomeSlider>
        )}

Hello guys, I just did it for multiple images, any remarks ?

import React from 'react';


class ImageUpload extends React.Component {
    state = {
        files: [],
        imagesPreviewUrls: []
    };

    _handleImageChange = e =>{
        e.preventDefault();

        // FileList to Array
        let files = Array.from(e.target.files);

        // File Reader for Each file and and update state arrays
        files.forEach((file, i) => {
            let reader = new FileReader();

            reader.onloadend = () => {
                this.setState(prevState => ({
                    files: [...prevState.files, file],
                    imagesPreviewUrls: [...prevState.imagesPreviewUrls, reader.result]
                }));
            }

            reader.readAsDataURL(file);
        });
    }

    render() {
        let {imagesPreviewUrls} = this.state;

        return (
            <div>
                <label className="btn btn-default btn-sm z-depth-0 mr-0 pl-2 pr-2 custom-file-upload waves-effect waves-light" htmlFor="file">
                    <i className="fas fa-image fa-fw" aria-hidden="true"></i>
                    <input className="upload" type="file" onChange={this._handleImageChange} multiple/>
                </label>
                {imagesPreviewUrls.map(function(imagePreviewUrl, i){
                    return <img key={i} src={imagePreviewUrl} />
                })}
            </div>
        )
    }
}


export default ImageUpload;

@watchDOGGGG
Copy link

dude your a life saver it help me alot

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment