Building a Video Player in React
Tags: react, javascript, webdev, beginners
Published: 2023-01-04 11:30:00

# Introduction

React has been the most popular JavaScript framework for building frontend. As a web developer, I recommend you learn React. For learning, nothing is better than building a project with that. 

I have written many articles about building stuff in React. In this last one, I wrote about [Building a Music Player in React](https://dev.to/documatic/building-a-music-player-in-react-2aa4). This time, I will guide you on building a video player in React. 

In this article, we are going to look into the following topics:
- Prerequisite and Setting up the Environment
- Playing Video with the default player
- Building a Custom player with Play/Pause functionality
- Adding the current time and duration of the video in the player
- Adding a range timeline to display the video

In the end, our player will look like this:

![Video Player](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2hgmyvuxigxcyaa0j4d8.png)

I hope that the above topics got you excited. Now, let's get started with the project.  

# Prerequisite and Setting up the Environment

I assume that you know of the following technologies as a prerequisite:

- JavaScript
- HTML/CSS
- Basic React

The environment setup is easy. You should have [node.js](https://nodejs.org/en/) pre-installed for running the node-related command in the terminal.

Navigate to the directory in which you want to create the project. Now, run the terminal and enter the below command to install react project.

```bat
npx create-react-app video-player
```

Remove all the boilerplate and unnecessary code. 

## Dependiencies

We need only one library to install. Here it is:

[react-icons](https://react-icons.github.io/react-icons/): For adding icons of play, pause, next and previous into our player.

Install it with the below command:

```bat
npm i react-icons
```

Now, We are good to go.

# Playing Video with the default player

Let's first import and play a video file in the browser. We can do that with the `video` HTML tag. 

Open App.js. Here is the code for it.

```jsx
import video from "./assets/video.mp4";

return(
 <video controls width="70%" className="videoPlayer" src={video}></video>
)
```

This will play the video in the browser with the default player. It will be able to do the post of the work.

Now, it's time to build our own controls with custom icons.

# Builiding Custom player with Play/Pause functionality

First, we need to hide the controls from the default player. We can do that by removing `controls` properties from the `video` tag. 

Now, it's to add custom icons to the player. 

```jsx

           <div className="controls">
            <IconContext.Provider value={{ color: "white", size: "2em" }}>
              <BiSkipPrevious />
            </IconContext.Provider>
            {isPlaying ? (
              <button className="controlButton" onClick={handlePlay}>
                <IconContext.Provider value={{ color: "white", size: "2em" }}>
                  <BiPause />
                </IconContext.Provider>
              </button>
            ) : (
              <button className="controlButton" onClick={handlePlay}>
                <IconContext.Provider value={{ color: "white", size: "2em" }}>
                  <BiPlay />
                </IconContext.Provider>
              </button>
            )}
            <IconContext.Provider value={{ color: "white", size: "2em" }}>
              <BiSkipNext />
            </IconContext.Provider>
```

We also need to store the video properties in `useRef` hook to prevent re-render on changes. Also, we need some states to store data running. Here is the code for imports and useState.

```jsx
import { useEffect, useRef, useState } from "react";
import { IconContext } from "react-icons";
import { BiPlay, BiSkipNext, BiSkipPrevious, BiPause } from "react-icons/bi";


function App() {
   const videoRef = useRef(null);
   const [isPlaying, setIsPlaying] = useState(false); // a boolean for storing state of the play
}
```

To `useRef` we just need to use the `ref` attribute in the `video` tag. 

```jsx
<video
   className="videoPlayer"
   width="70%"
   ref={videoRef}
   src={video}
></video>
```

We can do the play pause of the video with the `handlePlay` function. I have added it as the `onClick` button event in the icon's parent `div`.

Here is the code for the `handlePlay()`

```jsx
const handlePlay = () => {
  if (isPlaying) {
    videoRef.current.pause();
    setIsPlaying(false);
  } else {
    videoRef.current.play();
    setIsPlaying(true);
}
``` 

For CSS, you can see the below code:

```css
.container {
  display: flex;
  margin: 0 auto;
  justify-content: center;
  width: 80%;
  /* overflow: hidden; */
}

.playerContainer {
  display: flex;
  flex-direction: column;
  margin-top: 5em;
  border-radius: 1em;
  overflow: hidden;
}

.videoPlayer {
  border-radius: 1em;
  z-index: -1;
}

.controlsContainer {
  margin-top: -3.5em;
}

.controls {
  display: flex;
  z-index: 1;
  color: white;
  width: 200px;
  justify-content: space-between;
}

.controlButton {
  border: none;
  background: none;
}

.timeline {
  width: 70%;
}

.duration {
  display: flex;
  justify-content: center;
  align-items: center;
}

.controlButton:hover {
  cursor: pointer;
}
```

Now, our custom player can play/pause the video with our custom icon. 

# Adding the current time and duration of the video in the player

Let's first add a few more states for storing data related to the duration of the video. I have used the 

```jsx
  const [currentTime, setCurrentTime] = useState([0, 0]); // current time of the video in array. The first value represents the minute and the second represents seconds.
  const [currentTimeSec, setCurrentTimeSec] = useState(); //current time of the video in seconds
  const [duration, setDuration] = useState([0, 0]); // // total duration of the video in the array. The first value represents the minute and the second represents seconds.
  const [durationSec, setDurationSec] = useState(); // // current duration of the video in seconds
``` 

To get all the above data, we have the useEffect function.

```
useEffect(() => {
    const { min, sec } = sec2Min(videoRef.current.duration);
    setDurationSec(videoRef.current.duration);
    setDuration([min, sec]);

    console.log(videoRef.current.duration);
    const interval = setInterval(() => {
      const { min, sec } = sec2Min(videoRef.current.currentTime);
      setCurrentTimeSec(videoRef.current.currentTime);
      setCurrentTime([min, sec]);
    }, 1000);
    return () => clearInterval(interval);
  }, [isPlaying]);
```

To update the current time of the video, we have passed it as setTimeout function. This will update the current time of the video every second.

Also, there is a function `sec2Min()` for converting seconds into minutes. Here is the code for it.

```javascript
const sec2Min = (sec) => {
    const min = Math.floor(sec / 60);
    const secRemain = Math.floor(sec % 60);
    return {
      min: min,
      sec: secRemain,
    };
  };
```

Let's add it to the return of the app. 

```jsx
<div className="duration">
    {currentTime[0]}:{currentTime[1]} / {duration[0]}:{duration[1]}
</div>
```

# Adding a range timeline to display the video

Now, let's add a timeline to our player. We can do that by adding an `input` with `type="range"`. Here, the second of the current time and duration time will be helpful.

```jsx
<input
  type="range"
  min="0"
  max={durationSec}
  default="0"
  value={currentTimeSec}
  className="timeline"
  onChange={(e) => {
    videoRef.current.currentTime = e.target.value;
  }}
/>;
```

# CodeSandbox

You look for the code and the output in the below codesandbox. 

{% codesandbox immutable-sun-1bptx8 %}

# Adding more features to the player

You can extend the project to add features such as:
- Making the player more responsive
- Implementing full-screen button on the right
- Show controls only when hovering
- More features for your player according to what you

# Conclusion

We have created our own custom video player with play/pause and a timeline. I hope that the project has helped you in handling video in React.

Thanks for reading the article.