How to create a simple React component that keeps track of the “Page Visibility State”

Table of contents:

How to create a simple React component that keeps track of the “Page Visibility State”
How to create a simple React component that keeps track of the “Page Visibility State”

When building a web application, you may encounter situations where you need to track the current visibility state. It happens that you need to play or pause an animation or video effect, reduce the intensity or track user behavior for analytics. At first glance, this function seems quite simple to implement, but it is not entirely true. Tracking user activity is a rather complicated process.

There is a Page Visibility API that works great in most cases, but does not handle every possible case of browser tab inactivity. The Page Visibility API dispatches a visibilitychange event to let listeners know that the page's visibility state has changed. It does not fire the event in some cases if the window or corresponding browser tab is hidden from view. To handle some of these cases, we need to use a combination of focus and blur events on both document and window.

So, in this article, you will learn how to create a simple React component that tracks the Page Visibility State.


This is where Codesandbox will be used to create a React app (you can also use create-react-app). We will create a small application in which the HTML5 video element will only play if the browser tab is focused or active, otherwise it will be paused automatically. Video is used to make it easier to test the functionality of the application.


Step 1. Start by creating the simplest part, the video component

This will be a simple component with Boolean active and String src parameters containing the URL for video. If active props is true, the video will play. Otherwise, it will be stopped.

From pageVisibilityUtilsjs to srcdirectory
From pageVisibilityUtilsjs to srcdirectory

Step 2. Create a simple React class and a video element with its source code, accepting the URL passed by src

This uses the new ref API to attach a link to the DOM-node video. Let's set the video to autoplay, assuming that when we launch the application, the page will be active.

Safari does not automatically play media items without user interaction. The componentDidUpdate method is very handy for handling effects when a component property changes. Therefore, this method will be used here to play and pause the video based on the current value of

Step 3. Create a utility function

Differences in browser prefixes are not always convenient for certain APIs, and the Page Visibility API is one of them. We will create a simple utility function that will handle these differences and return a consistent API based on the user's browser. Create and export this function from pageVisibilityUtils.js in the src directory.

In this function, we will use an if-else statement to return a browser-specific API. You can see that we are adding the ms prefix for Internet Explorer and the webkit prefix for Webkit browsers. We will store the desired API in the hidden and visibilityChange variables and return them from the function as a simple object. Finally, we export the function

Step 4. Go to the main component

We will encapsulate all of the page visibility tracking logic in our React component class using the Render Props template. Create a component class VisibilityManager. This component will handle adding and removing all events based on DOM listeners. Step 5. Start by importing the previously created helper function and calling it to get the correct browser APIs.

Then create a React component and initialize its state with a single isVisible field set to true. This Boolean field will be responsible for the page's visibility state.

His.forceVisibilityTrue and this.forceVisibilityFalse
His.forceVisibilityTrue and this.forceVisibilityFalse

Step 6. In componentDidMount, add an event listener to the document for visibilitychange using the this.handleVisibilityChange method as a handler

Also add an event listener for the focus and blur events on the document, as well as the window element. This time, we'll set this.forceVisibilityTrue and this.forceVisibilityFalse as handlers for the focus and blur events. Step 7. Next, create a handleVisibilityChange method that takes a forceFlag argument.

The forceFlag argument will be used to determine if the method was called due to a visibilitychange event or focus and blur events. This is because the forceVisibilityTrue and forceVisibilityFalse methods do nothing but call the handleVisibilityChange method with true and false values for forceFlag. Step 8. Inside the handleVisibilityChange method, first check if the value of the forceFlag argument is boolean (if called from a visibilitychange event handler, then the passed argument will be a SyntheticEvent object).

  • If it is Boolean, check if it is true or false. When the value is true, call the setVisibility method with true or call the method with false. The setVisibility method uses the this.setState method to update the isVisible value in the component state.
  • If forceFlag is not Boolean, check the value of the hidden attribute in document and call the setVisibility method accordingly. This completes the logic for tracking the page's visibility state.

Step 9. Make the component reusable

To do this, use the Render Props pattern. That is, instead of rendering the component from the render method, we call this.props.children as a function with this.state.isVisible. Step 10: Install the React application to the DOM in the index.js file.

Import the two React components VisibilityManager and Video and create the App component by connecting them. We pass the function as a child of the VisibilityManager component, which takes isVisible as input and passes it to the Video component as output. Also pass the video url as src for the Video component. This is how the Render Props-based VisiblityManager component is applied. Finally, we use the ReactDOM.render method to render the application to a DOM-node with the identifier "root".

Popular by topic