React Native - Scroll in to element after dynamically adding the element

Viewed 1634

I dynamically adding/removing elements and when the added element is not in the view port, I want to get that in to the view port by scrolling in to the added element.

However I can't get it working. I am using measure function to get the coordinates and then scrollTo function to scroll to the element.

Here is the parent component with scroll view

  const scrollTo = (config) => {
    scrollElRef.current.scrollTo(config);
  };

  return (
    <ScrollView style={styles.container} ref={scrollElRef}>
      <Text style={styles.paragraph}>
       aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto
        beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia
        voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni
        dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam
        est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit.
      </Text>
      <Card>
        {items.map((i) => <AssetExample key={i} scrollTo={(c) => scrollTo(c)}/>)}
      </Card>
    </ScrollView>
  );
}

Here is the child component which add/remove element and sends the coordinates to the parent view

  React.useEffect(() => {
    if(asset) {
       elRef.current.measure((x, y, w, h, pageX, pageY) => {
          const elementBottom = pageY + h;
          const isInViewport = elementBottom < height;
          if (!isInViewport) {
            scrollTo({y: pageY, animated: true});
          }
        });
    }
  }, [asset, scrollTo, height])

Here is a sample App, which shows the problem.

https://snack.expo.io/@samithaf/blissful-yogurt

2 Answers

For ScrollView you need to provide specific height to its child component to make it work. Instead of dynamic, just provide specific height.Hope it works after that!

The content I have is dynamic due to the nature of the application. Therefore I came up with a different solution and it works without specifying a height. Here is how I did it, ( in here I calculate the area out side of the viewport.

elRef.current.measure((x, y, w, h, pageX, pageY) => {
        const elementBottom = pageY + h;
        const isInViewport = elementBottom < height;
        if (!isInViewport) {
          scrollTo(elementBottom - height);
        }
      });

Then in the scroll view you have listen to the scroll event, and when scrollTo function get called, all you have to do is get the current scroll position + area out side the viewport. Hope this helps anyone who wants achieve a similar result without hardcoding the height.

const scrollTo = (diff) => {
    scrollElRef.current.scrollTo(pageScrollY + diff);
  };
Related