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.
Try it out
We completed this project in CodeSandbox. You can fork the CodeSandbox project or run the code to get started quickly.
Prerequisites & Installation
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:
1yarn 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:
1npx 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:
1yarn add cloudinary-react
Video player utilization
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:
1import { Video, CloudinaryContext, Transformation } from "cloudinary-react";2 export default function IndexPage() {3 return (4 <div>5 Hello World.{" "}6 <CloudinaryContext cloudName="chuloo">7 <Video publicId="video-blog/cat" controls muted width="500px"/>8 </CloudinaryContext>9 </div>10 );11 }
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.
Video events handling
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:
1import { Video, CloudinaryContext, Transformation } from "cloudinary-react";2 import { useRef } from "react";3 export default function IndexPage() {4 const videoRef = useRef();5 return (6 <div>7 Hello World.{" "}8 <CloudinaryContext cloudName="chuloo">9 <Video publicId="video-blog/cat" controls muted width="500px"10 innerRef={videoRef}/>11 </CloudinaryContext>12 </div>13 );14 }
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:
1import { useRef, useEffect, useState } from "react";2 export default function IndexPage() {3 const [videoEnded, setVideoEnded] = useState(undefined)4 const videoRef = useRef()5 useEffect(() => {6 const video = videoRef.current;7 video.onpause = () => {8 // logic goes in here9 }10 video.onended = () => {11 setVideoEnded(true)12 // logic goes in here13 }14 }, [])15 return (16 // render component here17 );18 }
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:
1yarn add react-hot-toast
In the .onpause
and .onended
functions, we trigger success toasts using the toast
functions with:
1import { toast, Toaster } from "react-hot-toast";2 export default function IndexPage() {3 // component logic goes in here45 useEffect(() => {6 const video = videoRef.current;7 video.onpause = () => {8 toast.success("The video is paused");9 };10 video.onended = () => {11 setVideoEnded(true);12 toast.success("The video is ended");13 };14 }, []);1516 return (17 // rendered component goes in here18 );19 }
To see the toasts, we render the imported Toaster
component anywhere in the app.
1import { Video, CloudinaryContext, Transformation } from "cloudinary-react";2 import { useRef, useEffect, useState } from "react";3 import { toast, Toaster } from "react-hot-toast";4 export default function IndexPage() {5 // component logic definitions go in here67 return (8 <div>9 <Toaster />10 Hello World.{" "}11 <CloudinaryContext cloudName="chuloo">12 <Video13 publicId="video-blog/cat"14 controls15 muted16 width="500px"17 innerRef={videoRef}18 />19 </CloudinaryContext>20 </div>21 );22 }
Here’s what the final video looks like with the toasts on video events:
Conclusion
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: