# Understand onViewableItemsChanged in FlatList

post ime : 2020-01-21 category : React Native read :

If you want to get viewable items in the [FlatList], you had better take a look at the onViewableItemsChanged prop. For example, suppose you have a video list, and you want automatically play the video when the video is appearing on the screen for a few seconds. In iOS, there is visibleCells in UITableView to achieve this. In React Native, I am glad to tell you that FlatList has a more powerful property, onViewableItemsChanged. This article would help you better understand how to use theonViewableItemsChanged prop in the [FlatList], and how it works under the hood.

## What is onViewableItemsChanged

onViewableItemsChanged is a prop in VirtualizedList and FlatList. When you scroll a FlatList, the items showing on the FlatList change. Then, this function is called, telling you what current viewableItems are and what changed items are.

This function should be used together with viewabilityConfig. A specific onViewableItemsChanged will be called when its corresponding ViewabilityConfig‘s conditions are met.

Here is ViewabilityConfig

Here is the type of onViewableItemsChanged function:

## How to use it

Let’s look at two simple example.

Besides, supposed you have to implement different logic for items with 60% viewable region and those with 75% viewable region. You can use viewabilityConfigCallbackPairs, which contains an list of key/value objects, which define different viewability configurations and onViewableItemsChanged callbacks.

## How does onViewableItemsChanged works

### Viewable Region

The layout and viewable region information for VirtualizedList is stored in _scrollMetrics object. Through the nativeEvent in onScroll callback, VirtualizedList gets these layout information.

If it is a vertical VirtualizedList, the layout.layoutMeasurement.height in the nativeEvent is assigned to visibleLength; which is the height of viewable region here. Also, in a vertical VirtualizedList, the layout.layoutMeasurement.height is equal to viewportHeight.

### Overview

#### Different viewabilityConfig in one VirtualizedList

_viewabilityTuples is an array inside VirtualizedList to store ViewabilityHelper/onViewableItemsChanged pairs. This array is initialized in the constructor function.

If you define viewabilityConfigCallbackPairs, each viewabilityConfig will be used to initialize a different ViewabilityHelper object.

ViewabilityHelper is a utility class for calculating viewable items based on the viewabilityConfig and metrics, like the scroll position and layout.

As I mentioned before, in a VirtualizedList could has several ViewabilityHelper objects in _viewabilityTuples, containing different viewabilityConfig to handle different viewability conditions. Let’s take a look at some important props in ViewabilityHelper.

#### Items’ layout

In the overview graph, you can see a func _updateViewableItems called in many scenarios. For example, it is called in onScroll callback. Then, It calls viewabilityHelper.onUpdate to find out the viewable items, which appear in the viewport for VirtualizedList.

• this._scrollMetrics.visibleLength is used as viewportHeight
• this._createViewToken is used to construct a ViewToken object, which contains item data, index, key and isViewable flag of the item.
• this._getFrameMetrics is a function to get layout information of the item cell by index. The item layout is from getItemLayout prop of VirtualizedList or this._frames map. this._frames stores the itemKey/itemLayout pairs.
• By this.state, we know the range of the rendered items by first and last value. VirtualizedList updates these two values when the rendered items are changed.

### How to find out viewable items

In onUpdate method, it calls computeViewableItems to get viewableIndices. viewableIndices is an array of indexes of the viewable items. So, how does computeViewableItems work?

#### How to get the indexes of viewable items

In computeViewableItems in the ViewabilityHelper class, it iterates items from ${first} to ${last}. If an item is viewable, it will be stored in an array named viewableIndices.

From the code, we can see the top and bottom value is related to the screen coordinate. I drew a graph to show the relationship between metrics.offset, scrollOffset, metrics.length , top and bottom, to help you better understand the above code.

### What kind of item is viewable

An item is said to be viewable when it meets the following conditions
for longer than ${minimumViewTime} milliseconds (after an interaction if waitForInteraction is true): 1. the fraction of the item visible in the view area >= itemVisiblePercentThreshold. When it comes to the fraction of the item visible in the view area, we need to care about cases shown in the following graph. RN use Math.min(bottom, viewportHeight) - Math.max(top, 0) to calculate the viewable length. 2. Entirely visible on screen when the height of a item is bigger than the viewportHeight. ref code here ### Timer and Schedule In onUpdate func in ViewabilityHelper, if we define minimumViewTime value, the _onUpdateSync is scheduled to be called. It is the handler of the timeout. And, If after a few seconds,${minimumViewTime}, if some items aren’t longer viewable, the _onUpdateSync func, filter out these indices that have gone out of viewport.

In the above graph, at first, the _viewableIndices is from 1 to 9. Then the user scrolls the VirtualizedList and the _onUpdateSync is triggered after minimumViewTime. At this moment, the current _viewableIndices is from 2 to 10. So the item indexed 1 is filtered out.

### 6. How to get changed items

Comparing with the last time when onViewableItemsChanged is triggered, at this time to trigger onViewableItemsChanged. Some viewable items will be out of the screen, some hidden items will become viewable. In _onUpdateSync function, the preItems map stores the information about previous visible items, the previous means last time when VirtualizedList calls onViewableItemsChanged. Now it has a nextItems map, which stores the information about viewable items this time. Then it figures out the changed items by comparing these two maps. Then, it calls onViewableItemsChanged, passing viewableItems and changed` items.

Author : RY Zheng