Interactivity is at the backbone of modern web pages. This includes collecting information on user interaction, handling form submissions, and managing interactivity on media assets.
This post discusses how to handle user interface interactions with events from a Video on a Next.js web page.
Next.js is a modern React.js framework for building high-performance web applications.
We completed this project in CodeSandbox. You can fork the CodeSandbox project or run the code to get started quickly.
For this post, knowledge of JavaScript and React.js is required. The knowledge of Next.js isn’t mandatory, but preferred.
To create a new project, we use the create next-app
command to scaffold a new project. Using yarn, we run:
yarn create next-app
A prompt appears to enter the project name, which we do to complete the project creation.
Alternatively, we could use NPX with the command:
npx create-next-app
The boilerplate project scaffolds a landing page with styling using CSS modules.
For this project, we’ll use the Cloudinary-React package to render a video player whose video source is a video stored on Cloudinary. The video is delivered via an optimized content delivery network (CDN), and can be modified using Cloudinary’s robust transformation features.
We install the cloudinary-react package using yarn:
yarn add cloudinary-react
The cloudinary-react package exports two named components, Video
and CloudinaryContext
, which we’ll use to render the video player.
On the home page whose component is defined in pages/index.js
, we import and render the video player with:
import { Video, CloudinaryContext, Transformation } from "cloudinary-react";
export default function IndexPage() {
return (
<div>
Hello World.{" "}
<CloudinaryContext cloudName="chuloo">
<Video publicId="video-blog/cat" controls muted width="500px"/>
</CloudinaryContext>
</div>
);
}
Code language: JavaScript (javascript)
CloudinaryContext
receives props of any data we would like to make available to the Cloudinary child components. In this case, we passed our Cloudinary cloud name. You can obtain yours by creating an account on Cloudinary.
We use the Video
component to render the video player with a width of 500px. We also specified the video’s public ID, which is stored on Cloudinary. Lastly, we included props that give the video player controls and make it muted on render.
The video player currently looks like this:
The cloudinary-react video player is a wrapper on the traditional HTML5 video element with enhanced properties. It provides an innerRef
prop that grants us access to the underlying video element’s methods and properties.
With this, we will use React’s useRef()
hook to reference the video element.
With the Video
component’s ref, we’ll be able to utilize the onpause
and onended
events along with all other video events and properties. We create a ref and assign it to the innerRef
prop of the Video
with:
import { Video, CloudinaryContext, Transformation } from "cloudinary-react";
import { useRef } from "react";
export default function IndexPage() {
const videoRef = useRef();
return (
<div>
Hello World.{" "}
<CloudinaryContext cloudName="chuloo">
<Video publicId="video-blog/cat" controls muted width="500px"
innerRef={videoRef}/>
</CloudinaryContext>
</div>
);
}
Code language: JavaScript (javascript)
With the ref in place, we will handle actions when video events are triggered. We assign two functions, which we call when the video is paused, and the video ends. We do this in a useEffect
hook with:
import { useRef, useEffect, useState } from "react";
export default function IndexPage() {
const [videoEnded, setVideoEnded] = useState(undefined)
const videoRef = useRef()
useEffect(() => {
const video = videoRef.current;
video.onpause = () => {
// logic goes in here
}
video.onended = () => {
setVideoEnded(true)
// logic goes in here
}
}, [])
return (
// render component here
);
}
Code language: JavaScript (javascript)
In the imported useEffect
hook, we created a function that triggers when the video is paused or ended.
When the video ends, we store a true
boolean value in the component’s state. With this state value, we can handle multiple UI updates. These interactions include:
- Toasts to display status updates
- Modals to communicate important information
- Ads
- Call to action buttons when a video ends
- Handle navigation on specific video events
- Fetch or post data
The interactivity opportunities are boundless.
We will be rendering a timed toast component that fires when the video is paused or ends for this project. We use react-hot-toast for this.
React-hot-toast is a lightweight toast package that is seamless to use. We install it using yarn with the command:
yarn add react-hot-toast
In the .onpause
and .onended
functions, we trigger success toasts using the toast
functions with:
import { toast, Toaster } from "react-hot-toast";
export default function IndexPage() {
// component logic goes in here
useEffect(() => {
const video = videoRef.current;
video.onpause = () => {
toast.success("The video is paused");
};
video.onended = () => {
setVideoEnded(true);
toast.success("The video is ended");
};
}, []);
return (
// rendered component goes in here
);
}
Code language: JavaScript (javascript)
To see the toasts, we render the imported Toaster
component anywhere in the app.
import { Video, CloudinaryContext, Transformation } from "cloudinary-react";
import { useRef, useEffect, useState } from "react";
import { toast, Toaster } from "react-hot-toast";
export default function IndexPage() {
// component logic definitions go in here
return (
<div>
<Toaster />
Hello World.{" "}
<CloudinaryContext cloudName="chuloo">
<Video
publicId="video-blog/cat"
controls
muted
width="500px"
innerRef={videoRef}
/>
</CloudinaryContext>
</div>
);
}
Code language: JavaScript (javascript)
Here’s what the final video looks like with the toasts on video events:
This post discussed using a video player in a Next.js app, hook into the video element’s native properties, events, and methods using useRef
. We also handled UI changes on the page when a user fires video events.
Furthermore, you can handle data fetching and sending, or Ad display on your Next.js page using video events.
You may find these resources useful: