jjlmc
jjlmc

Reputation: 93

Preview image upload with React Functions

hello im trying to make a image upload and preview but i can only find react tutorials on how to do this using class components

import React from 'react';


const AddNew = () => {
    const fileHandler = (event) => {
        console.log(event.target.files[0])
    }
    const alt = (event) => {
        return(event.target.files[0].name)
    }
    const preview = (event) => {
        return (
            URL.createObjectURL(event.target.files[0])
        )
    }
    return (
        <div className="addNew">
            <img src={preview} alt={alt}/>
            <input type="file" onChange={fileHandler} />
        </div>
    )
}

export default AddNew

how do i preview it using this syntax?

i get an error for invalid values for props 'src' and 'alt'

Upvotes: 6

Views: 8616

Answers (3)

lhoro
lhoro

Reputation: 438

You need to use state to let React know when to re-render. You can use useState hook to save your component state and file information, and when it changes, React knows it's the time to render.

const AddNew = ({}) => {
    const [file, setFile] = React.useState(null)
    
    const fileHandler = (e) => {
        setFile(e.target.files[0])
    }
    
    return (
        <div>
            <img src={file? URL.createObjectURL(file) : null} alt={file? file.name : null}/>
            <input type="file" onChange={fileHandler} />
        </div>
    )
}



ReactDOM.render(<AddNew />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"/>

Upvotes: 9

Drew Reese
Drew Reese

Reputation: 202575

Use a bit of state to provide an initial value for src and alt and hold the updated values.

const initialState = { alt: "", src: "" };

const AddNew = () => {
  const [{ alt, src }, setPreview] = useState(initialState);

  const fileHandler = event => {
    const { files } = event.target;
    setPreview(
      files.length
        ? {
            src: URL.createObjectURL(files[0]),
            alt: files[0].name
          }
        : initialState
    );
  };

  return (
    <div className="addNew">
      <img className="preview" src={src} alt={alt} />
      <input accept="image/*" type="file" onChange={fileHandler} />
    </div>
  );
};

Edit image preview

Upvotes: 3

gdh
gdh

Reputation: 13682

You need to use FileReader to convert the image to base64 string. Assuming you are doing a single file upload, just maintain a state for eg: file and set the state after the filereader onload listener is done reading image.

Working copy of your code is here:


import React, { useState } from "react";

const AddNew = () => {
  const [file, setFile] = useState(null);
  const fileHandler = event => {
    console.log(event.target.files[0]);
    let reader = new FileReader();
    reader.onload = function(e) {
      setFile(e.target.result);
    };
    reader.readAsDataURL(event.target.files[0]);
  };

  return (
    <div className="addNew">
      <img src={file} alt={""} />
      <input type="file" onChange={fileHandler} />
    </div>
  );
};

export default AddNew;

Upvotes: 0

Related Questions