Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get image preview before uploading in React

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:

enter image description here

like image 553
Sylar Avatar asked Jun 27 '16 09:06

Sylar


People also ask

How do I show preview of an image before reacting in react JS?

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.

How do you preview selected image in input type file React?

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.


2 Answers

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>
 )
}
like image 71
Piyush.kapoor Avatar answered Oct 17 '22 20:10

Piyush.kapoor


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>
    )
}
like image 81
Jay Wick Avatar answered Oct 17 '22 21:10

Jay Wick