DEV Community

Cover image for Preview File before uploading in React
Jatin Sharma
Jatin Sharma

Posted on • Edited on • Originally published at j471n.in

Preview File before uploading in React

This article will explain how you can build a file previewer in React that works for images and videos. With this article's help, you can create your own and make support for other files.

This article only showcases the preview for an image and video.

Demo

demo

Creating FilePreviewer Component

First, let's just create a file components/FilePreviewer.js after that we need to import two things in that file useState and useRef.

// components/FilePreviewer.js
import { useState, useRef } from "react";
Enter fullscreen mode Exit fullscreen mode

Create a FilePreviewer function and export it as default.

// components/FilePreviewer.js
// ....
export default function FilePreviewer() {}
Enter fullscreen mode Exit fullscreen mode

Now we render the UI for FIle Picker and in that there will be two buttons. One for selecting files and the other for clearing file input. Let's see how it's going to look like.

// components/FilePreviewer.js

import { useState, useRef } from "react";
export default function FilePreviewer() {
  return (
    <div>
      <h1>Preview Image/Video</h1>
      <div className="btn-container">
        <input type="file" accept="image/*, video/*"  hidden />
        <button className="btn">Choose</button>
        <button className="btn">x</button>
      </div>
      <div className="preview">
        <img src="" alt="" />
        <video controls src=""></video>
      </div>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

This is just a starter code, I am going to add more things to this. First, understand what is going on. As you can see inside the btn-container class there are three inputs. One for selecting files but I won't use standard file input because when the user selects the file by standard input it shows the name of the file which I don't want (as shown in the following screenshot).

filename shows

Handling File Input button

I have created a new button to choose the file. To make this work we need to create a reference (ref) for file input. and handle the onChange event after that it will look something like this.

// components/FilePreviewer.js

import { useState, useRef } from "react";

export default function FilePreviewer() {
  return (
        // inside .btn-container
        <input ref={filePicekerRef} accept="image/*, video/*"  onChange={previewFile} type="file" hidden />
        // ...
  );
}
Enter fullscreen mode Exit fullscreen mode

We will create the previewFile function in just a moment to handle the file selection.

Creating Custom File input Button

Now as I have hidden the original file input button we need to create our own.

// components/FilePreviewer.js

import { useState, useRef } from "react";

export default function FilePreviewer() {
  return (
        // inside .btn-container
        <button className="btn" onClick={()=> filePicekerRef.current.click()} >
            Choose
        </button>
        // ...
  );
}
Enter fullscreen mode Exit fullscreen mode

In this, I am just triggering the file input button through ref when the user clicks this button.

File Selection

As we are handling two files (image and video). we need to create two states for that imagePreview and videoPreview.

// components/FilePreviewer.js

import { useState, useRef } from "react";

export default function FilePreviewer() {

  const [imagePreview, setImagePreview] = useState(null);
  const [videoPreview, setVideoPreview] = useState(null);

  return (
        // ...
  );
}
Enter fullscreen mode Exit fullscreen mode

Now its' time to create a filePreview function.

// components/FilePreviewer.js

export default function FilePreviewer() {
  // ...
  function previewFile(e) {
    // Reading New File (open file Picker Box)
    const reader = new FileReader();

    // Gettting Selected File (user can select multiple but we are choosing only one)
    const selectedFile = e.target.files[0];
    if (selectedFile) {
      reader.readAsDataURL(selectedFile);
    }

    // As the File loaded then set the stage as per the file type
    reader.onload = (readerEvent) => {
      if (selectedFile.type.includes("image")) {
        setImagePreview(readerEvent.target.result);
      } else if (selectedFile.type.includes("video")) {
        setVideoPreview(readerEvent.target.result);
      }
    };
  }
  // ...
}
Enter fullscreen mode Exit fullscreen mode

I know it's too much so let's break it down. I am using FileReader to handle the file selection.

  • I have created an instance called reader.
  • Then we are getting the selectedFile from an input field (I am targeting only one file, the user can select multiple files but I am handling only one file).
  • If the user has selected a file then read that as Data URLs.
  • When the file is loaded then check for the file type and set the image and video accordingly.

Preview the file

After file selection is done then we need to preview the file to the user. For that I have already created a container called .preview, In that, there were two elements img and video. Now we need to render these elements conditionally. and after that they will look like this-

// components/FilePreviewer.js 

<div className="preview">
    {imagePreview != null && <img src={imagePreview} alt="" />}
    {videoPreview != null && <video controls src={videoPreview}></video>}
</div>
Enter fullscreen mode Exit fullscreen mode

Clear Input Field

Now, what if the user wants to clear the input field or remove the image he has selected. We haven't implemented that yet. To do that I've created a close button earlier. Now let's just add the functionality to it. When the user clicks on the button then it should fire clearFiles function. So let's just create it.

// components/FilePreviewer.js 

function clearFiles() {
    setImagePreview(null);
    setVideoPreview(null);
}
Enter fullscreen mode Exit fullscreen mode

That's all we need to create a working file Previewer. It can preview an image and a video.

Full Code of FilePreviewer.js

// components/FilePreviewer.js 
import { useState, useRef } from "react";

export default function FilePreviewer() {
  // FIles States
  const [imagePreview, setImagePreview] = useState(null);
  const [videoPreview, setVideoPreview] = useState(null);

  // FIle Picker Ref because we are not useing the standard File picker input
  const filePicekerRef = useRef(null);

  function previewFile(e) {
    // Reading New File (open file Picker Box)
    const reader = new FileReader();

    // Gettting Selected File (user can select multiple but we are choosing only one)
    const selectedFile = e.target.files[0];
    if (selectedFile) {
      reader.readAsDataURL(selectedFile);
    }

    // As the File loaded then set the stage as per the file type
    reader.onload = (readerEvent) => {
      if (selectedFile.type.includes("image")) {
        setImagePreview(readerEvent.target.result);
      } else if (selectedFile.type.includes("video")) {
        setVideoPreview(readerEvent.target.result);
      }
    };
  }

  function clearFiles() {
    setImagePreview(null);
    setVideoPreview(null);
  }

  return (
    <div>
      <h1>Preview Image/Video</h1>

      <div className="btn-container">
        <input
          ref={filePicekerRef}
          accept="image/*, video/*"
          onChange={previewFile}
          type="file"
          hidden
        />
        <button className="btn" onClick={() => filePicekerRef.current.click()}>
          Choose
        </button>
        {(imagePreview || videoPreview) && (
          <button className="btn" onClick={clearFiles}>
            x
          </button>
        )}
      </div>

      <div className="preview">
        {imagePreview != null && <img src={imagePreview} alt="" />}
        {videoPreview != null && <video controls src={videoPreview}></video>}
      </div>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

Now we just need to import this container in App.js and render it. App.js will look something like this.

// src/App.js

import "./styles.css";
import FilePreviewer from "./components/FilePreviewer";

export default function App() {
    return (
        <div className="App">
            <FilePreviewer />
        </div>
    );
}
Enter fullscreen mode Exit fullscreen mode

You can find the full code in the following Sandbox

It takes a little white to render the video if the size of the video is large. You can setup a loading state for that.

What's Next?

Now after that you can take this further and add support for other files such as text, pdf, and others. You can also add support for multiple files and there are many things you can do.

Top comments (3)

Collapse
 
lico profile image
SeongKuk Han

It's easy to understand :) thanks for the good post

Collapse
 
j471n profile image
Jatin Sharma

Thanks for the appreciation ✨

Collapse
 
andrewbaisden profile image
Andrew Baisden

Good post.