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