How to implement a FlatList inside of a Pressable without scrolling getting disabled? - react-native

Basically, I want the FlatList to have a onPress functionality (to explain simply) as well as the default scrolling functionality. Right now, if I have a FlatList inside a Pressable, then I am not able to scroll through the FlatList.
I have also tried to put Pressable inside the FlatList's RenderItem component, but I have a lot of items I'll be displaying, so it's going to inefficient.

Instead of Pressable wrapping the FlatList, I learnt that we can use React Native's Gesture Responder System on a simple View to get the behavior that I require.
<View
onStartShouldSetResponder={() => true}
onResponderRelease={doSomethingFunction}
>
<FlatList
data={someData}
renderItem={renderItemComponent}
/>
</View>

Try touch handling on FlatList item parent container like below so the scrolling issue would never come again and you can easily handle the touch on each item separately
<FlatList
style={{...}}
data={[...]}
keyExtractor={(item, index) => index.toString()}
renderItem={({ item }) => (
<TouchableWithoutFeedback onPress={() => {...}}>
<View>
....
</View>
</TouchableWithoutFeedback>
)}
/>

Related

Is there a FlatList-like View without the scrolling?

Basically, I have a list of items (with images) inside a single Card (custom component). Because the rendering of those items is slow, I wanted to use a FlatList to render them incrementally.
Unfortunately, I get the expected error
VirtualizedLists should never be nested inside plain ScrollViews ...
But I don't actually want to use a ScrollView inside the Card. I just want to render a few Items in a single Card, which should change its size to fit all the items.
Setting scrollEnabled={false} on the FlatList still shows the error above.
Using the ListHeaderComponent and ListFooterComponent props is not an option, because the content above and below should NOT be rendered inside the Card.
Here is a minimal example of what I mean:
const Comp = () => {
return (
<ScrollView contentInsetAdjustmentBehavior="automatic">
<Text>Header</Text>
<Card>
<FlatList
data={data}
renderItem={({ item }) => (
<Image source={{uri: item.localImageUrl}}/>
)}
keyExtractor={(item) => item.id}
scrollEnabled={false}
initialNumToRender={0}
maxToRenderPerBatch={3}
contentInsetAdjustmentBehavior='automatic'
/>
</Card>
<Text>Footer</Text>
</ScrollView>
);
};
What's interesting though, that aside from the error - I get the result I expected, and I could technically hide that error and ignore it, but that does not seem like the recommended approach.
Important: I am not specifically looking for a FlatList solution. It could technically be any Component that renders items incrementally in a non-blocking way.
The important point with a Flatlist is the reusing of cells so that not all components need to be rendered at the same time. So scrolling is an important part of this. On the other hand two scrollable components inside eachother will make it impossible for the system to know which component should be scrolled.
If there are only 3 items and it should not be scrollable you can just include a list of items inside the Scrollview like this:
const Comp = () => {
return (
<ScrollView contentInsetAdjustmentBehavior="automatic">
<Text>Header</Text>
<Card>
{ data.map((item, index) => {
return (
<Text key={index}>{item.title}</Text>
);
}) }
</Card>
<Text>Footer</Text>
</ScrollView>
);
};

How to detect drag end in View React Native

I have a View. In this view I have a flat list that has the onScrollEndDrag and onScrollBeginDrag logic that works, except when the drag released on the bottom tab menu that is not part of the FlatList.
Because the handler is on the FlatList I can't detect drag releases that happen on the bottom tabs.
I need to have the drag end logic to be attatched to the view instead of the FlatList. How can I detect a when drag ends/the user releases the hand of the screen in the View instead of the FlatList?
Here is what I have currently:
<View>
<StatusBar barStyle={"light-content"} />
<FlatList
data={challenges}
renderItem={({ item, index }) => (
<ChallengePost challenge={item} isVideoPlaying={index === currentlyPlaying && !navigatedOutOfScreen} />
)}
keyExtractor={(challenge) => challenge._id}
showsVerticalScrollIndicator={false}
snapToInterval={Dimensions.get("window").height}
snapToAlignment={"start"}
decelerationRate={"fast"}
onViewableItemsChanged={onViewRef.current}
onScrollEndDrag={() => (scrollEnded.current = true)}
onScrollBeginDrag={() => (scrollEnded.current = false)}
></FlatList>
</View>
as you can see the onScrollEndDrag onScrollBeginDrag happends on the FlatList level and I want it be able to detect drag releases that happen on the entire screen.
Check this library it should help you make it easier because it wraps some of the components in its own pan gesture handlers
react-native-gesture-handler
examples

react-native: OnEndReached for Flatlist not working in scrollview

I'm new on ReactNative development and I'm developing my first application.
I'm trying to use OnEndReached in a flat list which is in a scrollview tab. I use this scrollview because I have 3 flat lists in my application.
The first two are horizontal. For the last one, I need to handle the pagination with the onEndReached. But, When I put this last flat list in the scroll view, it doesn't work at all without any issues.
When I put it out of the scrollview, it works correctly. So I assume the issue is related to that.
Do you know how I can manage this issue? I'm sorry if this question is a basic one :(
OnEndReached doesn't call if the parent has ScrollView. Why not put those top views in the Header?
<FlatList
data={data}
renderItem={}
keyExtractor={(item, index) => item.personId}
onEndReached={() => {
console.log(" On End Reached");
}}
onEndReachedThreshold={0.01}
ListHeaderComponent={() => (
<View>
<FlatList/>
<FlatList/>
</View>
))
/>

React Native - Flat list scrolling is not working in Pan Responder

React Native, Using PanResponder View as a parent and having flatlist as a child of the view, without PanResponder, flatlist scrolling is working fine but with PanResponder, flatlist scrolling is not working.
I dont find proper solution, but workaround is wrap the flatlist items in TouchableOpacity , it will make flatlist scrollable.
If you don't like TouchableOpacity's opacity then you can set activeOpacity to 1.
Example:
<View {...this.gestureHandlers.panHandlers} style={styles.container}>
<FlatList
horizontal={true}
data={this.state.FlatlistData}
renderItem={({ item }) => {
return (
<TouchableOpacity activeOpacity={1} style={styles.itemsStyle}>
{/* Your core view here */}
</TouchableOpacity>
)
}}
/>
</View>

React Native "keyboardDismissMode" at FlatList

Is there any possibility to prevent the keyboard from dismissing when scrolling a FlatList?
When using a ScrollView setting the prop "keyboardDismissMode" to "none" is the solution to this problem, but this doesn't work for me at a FlatList...
I use the FlatList inside a self-made component, that is in a Stack-Navigator, while there is a focussed TextInput in its header. I render the FlatList like this:
<View style={{flex: 1}}>
<FlatList
style={{flex: 1}}
data={this.props.data}
keyExtractor={(item, index) => item.id}
renderItem={this.renderItem}
/>
</View>
The renderItem() function:
renderItem = ({item, index}) => (
<TouchableHighlight
style={{paddingVertical: 10}}
onPress={() => {
this.props.onChooseItem(item);
}}
>
<Text numberOfLines={1} >
{item.text}
</Text>
</TouchableHighlight>
)
The docs at the beginning of the reference section says that FlatList "Inherits ScrollView Props, unless it is nested in another FlatList of same orientation."
So I think you can just do use that keyboardDismissMode without encapsulation in a scrollview.
No need of scrollview inside flatlist it will create performance issue.
just add onScrollBeginDrag={Keyboard.dismiss} in flatlist. it will work in android as well iOS while keyboardDismissMode='on-drag' will work only in iOS
You might think about to encapsulate your FlatList in a ScrollView?
Even if this seems to solve the issue, it's NOT a recommended way!
That's because if it force rerendering the whole flatlist, each time you scroll the screen.
You might better try a component like react-native-keyboard-aware-scroll-view
I've found this article with some alternate Ideas to fix it:
How to use KeyboardAvoidingView with FlatList?
Check: https://facebook.github.io/react-native/docs/scrollview#keyboarddismissmode