How to Determine Whether a Component Is Present in ViewPort

Hi guys, in this article we will learn about how to check the position of a component in the viewport, i.e., the viewable area on the mobile screen.

In React Native, you can use the onLayout prop of a component to determine its visibility on the screen. The onLayout the prop is called an event object that has a nativeEvent property containing the layout information for the component.

The onLayout method is called when a view’s layout is calculated. This typically happens when the view is added to a parent view or when the view’s layout is modified in some way, such as when the device’s screen orientation changes. The onLayout method is passed three parameters:

  1. A boolean indicating whether the view’s layout has changed
  2. The left position of the view, in pixels
  3. The top position of the view, in pixels

The onLayout method is typically used to determine the size and position of a view and its child’s views. It can be overridden in a custom view to perform custom layout calculations.

But now, we will go one step further and check the component’s visibility at any time, irrespective of the onLayout method call.

It is helpful if you want to send impression events on the server with information about the section the user sees in your app. It is also helpful in monitoring the ad impressions that are seen by users.

Prerequisite: You should have a basic understanding of mobile app development using React Native and its basic concepts.

Let’s kick off by creating a new React-Native project with the help of this command.

npx react-native init you_project_name

Now let’s create a default screen where we can render our components.

import React from "react";
import { View } from "react-native";

class Home extends React.PureComponent {
  constructor(props) {
    super(props);
  }

  render() {
    return <View></View>;
  }
}

export default Home;

Now, let’s create three different components: ChildOne, ChildTwo, and ChildThree.class

class ChildOne extends React.PureComponent {
  constructor(props) {
    super(props);
  }

  render() {
    return (
      <View
        style={{
          padding: 20,
          borderWidth: 2,
          justifyContent: "center",
          alignItems: "center",
          height: 500,
          backgroundColor: "yellow",
        }}
      >
        <Text style={{ color: "black" }}>Hi There!</Text>
        <Text style={{ color: "black" }}>I am child one</Text>
      </View>
    );
  }
}

Let’s have a look at the outcome of the work we’ve done so far!

Now wrap our child with a View component and get the refs of each child component.

{ this.childOneRef = component; }} > { this.childTwoRef = component; }} > { this.childThreeRef = component; }} >

To ensure that View exists in the native view hierarchy, set collapsable={false}.

Let’s assume we want to check whether ChildThree is in ViewPort or not.

Let’s now write a function that will notify us when the ChildThree component is in ViewPort.In this function, we will be using measure(callback), which simply determines the location on the screen, height, and width, and returns the value via an async callback.

Method: measure((x, y, width, height, pageX, pageY)) gives us the position of the View.

where x is X offset to frame, y is Y offset to frame and 
width = width of the View,

height = height of the View,

pageX = X offset to page,

pageY = Y offset to page.

We are using rectTop and rectBottom to identify the position of the component from the top and bottom of the screen, respectively.

checkIsInViewPort(){
    if(this.childThreeRef){
        this.childThreeRef.measure((x, y, width, height, pageX, pageY) => {
          const rectTop = pageX;
          const rectBottom = pageY + height;
          const  rectWidth = pageX + width;
          const window = Dimensions.get('window');
          const isVisible = rectBottom != 0 
                            && rectTop >= 0 
                            && rectBottom <= window.height 
                            && rectWidth > 0 
                            && rectWidth <= window.width;
          console.log('is in View Port :',isVisible);
        })
    }
  }

To demonstrate, I’m wrapping these three components inside ScrollView and calling the checkIsInViewPort function on ScrollView’s onScroll; however, this isn’t the best way to handle in-view ports in large applications.
It could be used in a variety of ways depending on the application.

You can take a look at the final code below.

import React from 'react';
import { View, Text, Dimension } from 'react-native';

class HomeScreen extends React.PureComponent {
    constructor (props) {
        super(props);
    }

  checkIsInViewPort(){
    if(this.childThreeRef){
        this.childThreeRef.measure((x, y, width, height, pageX, pageY) => {
          const rectTop = pageX;
          const rectBottom = pageY + height;
          const  rectWidth = pageX + width;
          const window = Dimensions.get('window');
          const isVisible = rectBottom != 0 
                            && rectTop >= 0 
                            && rectBottom <= window.height 
                            && rectWidth > 0 
                            && rectWidth <= window.width;
          console.log('ChildThree is in View Port ?:',isVisible);
        })
    }
  }

    render () {
      return (
          <SafeAreaView>
              <View style={{ flex: 1, backgroundColor: 'white' }}>
                <ScrollView 
                    onScroll={() => {
                        console.log('scrolling');
                        this.checkIsInViewPort();
                    }}
                >
                    <View
                        collapsable={false}
                        ref={(component) => {
                            this.childOneRef = component;
                        }}
                    >
                        <ChildOne />
                    </View>
                    <View
                         collapsable={false}
                         ref={(component) => {
                             this.childTwoRef = component;
                         }}
                    >
                        <ChildTwo />
                    </View>
                    <View
                         collapsable={false}
                         ref={(component) => {
                             this.childThreeRef = component;
                         }}
                    >
                        <ChildThree />
                    </View>
                </ScrollView>
              </View>
          </SafeAreaView>
      );
  }
}

export default HomeScreen;

class ChildOne extends React.PureComponent {
    constructor(props){
        super(props)
    }

    render(){
       return(
        <View style={{padding :20, borderWidth: 2, justifyContent:'center', alignItems:'center', height: 500, backgroundColor: 'yellow'}}>
            <Text style={{color: 'black'}}>Hi There!</Text>
            <Text style={{color: 'black'}}>I am child one</Text>
        </View>
       )
    }
}

class ChildTwo extends React.PureComponent {
    constructor(props){
        super(props)
    }

    render(){
       return(
        <View style={{padding :20, borderWidth: 2, justifyContent:'center', alignItems:'center', height: 500, backgroundColor: 'violet'}}>
            <Text style={{color: 'white'}}>Hi There!</Text>
            <Text style={{color: 'white'}}>I am child two</Text>
        </View>
       )
    }
}

class ChildThree extends React.PureComponent {
    constructor(props){
        super(props)
    }

    render(){
       return(
        <View style={{padding :20, borderWidth: 2, justifyContent:'center', alignItems:'center', height: 500, backgroundColor: 'grey'}}>
            <Text style={{color: 'white'}}>Hi There!</Text>
            <Text style={{color: 'white'}}>I am child three</Text>
        </View>
       )
    }
}

Thank You!! 

Latest

SENTRY integration in your React Native App for Error/Crash tracking

Sentry captures data by using an SDK within your...

Recall the concepts of useCallback.

useCallback hook is one of the best hooks offered...

Value of Comments in the code!!

During my journey of Software Development, I am always...

YOLO:Bullet Paced Algorithm

http://sh017.hostgator.tempwebhost.net/media/33949d0e61af4b50f374c534713f56b3 According to world health organization, more than 1.35 million...

Featured

Developing Enterprise Application in Node.js – CJS Vs ESM

Node.js is a popular runtime environment for building server-side...

Integrating your web react applications with their React Native(android and IOS) apps using QR code

Integrating a web application with Android and iOS apps...

YOLO: Bullet Paced Algorithm – popular choice for object detection in autonomous vehicles 

According to world health organization, more than 1.35 million...

Range Slider in React Native

There might be some scenarios such as show distance range or proficiency of skills in which we have to use a slider. So to...

Enhancing Performance and Optimization of React Native Applications

There are some ways to improve react-native app performance we will discusses one by one There are many approaches out there to avoid this issue. 1....

Best Practices for React State Management

React state management is a crucial aspect of building scalable and maintainable applications with React. State management helps in keeping track of data that...

LEAVE A REPLY

Please enter your comment!
Please enter your name here