Magazine

Deep Linking in React Native — Scroll to Element

Scroll through our first article about scrolling. Almost an infinite scroll. 👀

20 deep linking 2

This is the second part of our React Native Deep Linking series. Please follow this link to read the first part.

A nice addition to deep linking, mainly with scrollable pages, is the automatic scrolling animation to a specific element. It is mostly used in lists of homogeneous data, such as comments. It helps users see the exact element of their concern in an array of similar data. Say someone liked or replied to your comment and you receive a notification. When you tap on it — you are taken to the comment list and scrolled directly to the mentioned comment. Perfect.

This technique is often paired with some sort of a signal to mark the comment, like contrasting color highlights behind it or an animation.

So let’s see your options for creating an automatic scroll to the element of interest.

FlatList

The easiest way to get this working is to use the FlatList component — if it is compatible with your data on that screen. The important steps are:

1. Adding reference to your FlatList:

<FlatList
    ref={ref => {
      this.flatListRef = ref;
    }}
    // … other props …
/>

2. Referring to that list inside your component and execute functions:

this.flatListRef.scrollToIndex({
    animated: true,
    index: itemIndex,
});

3. Defining onScrollToIndexFailed, which is FlatList’s prop:

onScrollToIndexFailed={error => {
    this.flatListRef.scrollToOffset({
        offset: error.averageItemLength * error.index,
        animated: true,
    });

    setTimeout(() => {
        if (this.flatListRef !== null) {
            this.flatListRef.scrollToIndex({
                index: error.index,
                animated: true
            });
        }
    }, 100);
}}

I’ll let RN documentation do the talking for why this is necessary:

Used to handle failures when scrolling to an index that has not been measured yet. Recommended action is to either compute your own offset and scrollTo it, or scroll as far as possible and then try again after more items have been rendered.

And you’re done with the FlatList version — call scrollToIndex when you need it and let the magic happen. 🎩🐰

ScrollView

If you don’t have the ability to use FlatList, you can go for ScrollView and the following configuration. If you are using ScrollView, you probably have mixed data (e.g. an image, title, some buttons under it, etc.).

Unfortunately, in that case, you can’t rely on scrolling to a specific item by using its ID to work “out of the box” because you’re not exactly rendering a list of similar items here.

One of the solutions is to determine the desired element’s position on the screen and use it as an anchor point for auto-scroll. Here are the steps.

1. Once again, define ref on your view.

<FlatList
    ref={ref => {
      this.flatListRef = ref;
    }}
    // … other props …
/>

2. Now you can use another method called scrollTo, which looks something like this:

this.scrollViewRef.scrollTo({
    animated: true,
    y: viewY
});

The next question that might come up is “How do I get the y value for my element?”. Fear not! You can use onLayout and attach it to your RN component. onLayout is a prop of any React Native built-in component that originates from a View. That method is invoked on mount and layout changes of the component. Bear in mind — the x and y values are relative to the top left corner of the screen.

3. This is an example of stuff we can get information about regarding our view:

<View
  onLayout={event => {
    const { layout } = event.nativeEvent;
    console.log(‘height:’, layout.height);
    console.log(‘width:’, layout.width);
    console.log(‘x:’, layout.x);
    console.log(‘y:’, layout.y);
  }}
>

The one we need here is obviously y. Store it somewhere accessible and use it in the scrollTo method for viewY.

Et voilà! 🎉

Pairing it with deep linking

As per the title, let’s pair this feature with deep linking.

You’d want to send the item’s ID or some sort of a primary key through the link like: demo://home/first/:commentId

Then, we can call JS’s findIndex() on our array of data:

const { commentId } = this.props.navigation.state.params;
const commentIndex = commentsArr.findIndex(c => c.id === commentId);

and use commentIndex in the scrollToIndex() method.

You can find more details in the GitHub repo and the first part of the blog series.

Deep-linking with autoscrolling in action.

Let me leave you with a bonus tip:

If you need to use the sticky section header with separated data, look no further than React Native’s SectionList component. The use case for this is a notification list with the following section: Today, Yesterday, Older, etc., as seen on popular applications such as Instagram and Facebook.

Other than that, definitely check out the documentation for other commonly used functions for scrolling components like scrollToEnd or refreshControl.

Have fun and stay tuned for more! 📻 😊

Leave a comment Be the first!