3

Inside a FlatList I have accordions (by react-native-paper). When I scroll to any position and open/close an accordion, The FlatList scrolls to the top of the screen. How should I prevent it?

in another word when an accordion gets expanded, the content size is changed. How to stay where the user was on content size changes. The current snippet does not work and the stored y position resets.

  const flatListRef = React.useRef<FlatList<any>>(null);
  const yOffset = React.useRef<number>(0);

           <FlatList
             ref={flatListRef}
             data={properties}
             renderItem={renderItem}
             keyExtractor={(item) => `${item.id}`}
             onContentSizeChange={() =>{flatListRef.current!.scrollToOffset({offset: yOffset.current, animated: false});}}
             onEndReached={onEndReached}
             onEndReachedThreshold={0}
             scrollEventThrottle={15}
             onScroll={(e) => {yOffset.current = e.nativeEvent.contentOffset.y;}}
             ListFooterComponent={<ActivityIndicator animating={loading} size="small" />}
  />

for instance, (inside onContentSizeChange conosle.log(yOffset.current)) if I scroll to yOffset 850 and exapnd the accordion there, in console I see two logs, 850, then 126 (which 126 returns to the top) which indicates, onScroll was called and yOffset changed.

Amir-Mousavi
  • 4,273
  • 12
  • 70
  • 123
  • Can you put it in a codesandbox? – diedu Apr 01 '21 at 05:51
  • can you give minimal working code in expo snack? perhaps, then we be able to figure out the problem. – MRPMOHIBURRAHMAN Apr 02 '21 at 12:42
  • You can use `zIndex` for placing a view on top of another. Try putting your `FlatList` in a view or give it a class and use `zIndex`. It works like the CSS z-index property - components with a larger `zIndex` will render on top and they won't affect or change position of other elements. – Blessing Apr 06 '21 at 09:07

2 Answers2

0

The correct solution around this problem is to move the rendered Item out of your main component and manage its state(e.g. in the case of accordion) in that separate component. So that flatlist won't get re-rendered and hence will maintain its scroll position. I just implemented it myself and it worked.

const YourRenderItem = ({ item, index }) => {
 const [isExpanded, setIsExpanded] = useState(false);
 return (<YourComponent/>)
}
Praman
  • 19
  • 4
-1

Not sure about your question here, but if you don't want to scroll to top on accordion expansion, just remove onContentSizeChange and onScroll prop.

Also, if you want that on accordion press that should come on top of the screen just wrap the Accordion in a View and get the expanded height/xy coordinates of the View using the onLayout prop and then you can use the Flatlist's scrollToOffset() to scroll to that particular Accordion

kreysix
  • 359
  • 2
  • 11