FlatList is locking clicks when loading or refreshing data - react-native

I'm using FlatList component to handle massive amount of data with pagination (requesting 15 by 15 for tests).
<FlatList
data={this.state.noMatches? this.state.monitorados : this.state.filtrados}
keyExtractor={item => item.identificador}
ListFooterComponent={this.renderFooter}
refreshing={this.state.refreshing}
onRefresh={() => this.handleRefresh()}
style={styles.list}
onEndReached={() => this.handleScroll()}
onEndThreshold={0.5}
renderItem={({item}) => (<SimpleItem item={item} />)}
/>
I have a expand/collapse animation and nested components in each row. I'm using a custom component to handle the animation, some data-pickers, views, texts and other common.
When first 15 rows are rendered, I try to click to expand, but it do not responds immediately. Some seconds later I can click and the item expand, but its lagging a lot. More seconds, I can expand/collapse very well, every item of list react instantly.
If I slide down, 15 more items are requested and all that happens again: the clicks got locked, the first click lag so much, the next is highly performing.
Gif demo:
Question:
Can I somehow unlock clicks to expand/collapse even if component still loading?
Is there some way to optimize flatlist performance?
Already tried:
Moved nested components to other file and make it a Pure Component.
Removed styles.
Removed expand/collapse and test clicks in TouchableOpacity - same issue.

Related

stop ScrollView from scrolling

I want to stop a ScrollView from scrolling in React Native. I don't want to completely disable it, I just want it to stop scrolling at a specific point, so that I can scroll it again afterwards.
Since the scrolling momentum still persists afterwards, I can't simply disable it when a certain condition is met, so the following code does not work.
<ScrollView
onScroll={e => {
if (e.nativeEvent.contentOffset.y > 500) {
setStopScroll(true)
}
}}
scrollEnabled={!stopScroll}
/>
I omitted the part in which is enabled the scroll view again to continue scrolling.
You are looking for snapToOffsets. This takes an array of positions where you want it to stop. After it stops, if you scroll again, it will stop at the next offset. Also make sure snapToEnd is set to false.
<ScrollView
snapToOffsets={[100,500,800]}
decelerationRate="fast"
snapToEnd={false}
snapToStart={false}
disableIntervalMomentum={true}
onScroll={onScroll}
>
... your code here
</ScrollView>

Scrollview perfomance issue when using multidimensional array and using .map() twice inside the scrollview

I tried the flatlist but it doesn't let me scroll both sides.
if their is no option on the scrollview i wanted to know what kind of approach you would take to scroll on both sides vertically and horizontally
<Animated.ScrollView
ref={verticalScrollView}
nestedScrollEnabled
directionalLockEnabled={false}
scrollEnabled={true}
showsVerticalScrollIndicator={false}
showsHorizontalScrollIndicator={false}
onScroll={handleScrollEvent}
scrollEventThrottle={20}
centerContent={true}
>
{grid.map((grid, verticalIndex) => {
return (
<HorizontalView justify="">
{gird.map((item)=>{
return (
<View>rfr</View>
)
})}
</HorizontalView>
)})}
</Animated.ScrollView>
i tried the flatlist but the flatlist doesn't allow me to scroll both side vertically and horizontally.
my expectation is to create a table like ground structure using multi dimensional array and the array grows depending on the users performance i want also to make it scrollable on both sides

React Native handle touch release

I have a component which when the user long press a card I show a bigger version of this card.
The ideia is that the bigger card will be shown as long as the user keep pressing the touch and then will hide only when the finger is released (something like instagram long press). I tried to archieve this using the onLongPress and the onPressOut props of <TouchableHighlight>, the thing is that the onPressOut props has something that they call "cancel",
/**
* Called when the touch is released,
* but not if cancelled (e.g. by a scroll that steals the responder lock).
*/
What is happening is that when the user hold and move the finger the onPressOut prop is called, therefore the bigger card is hidden.
This is the code:
<View style={styles.container}>
<View style={styles.separator}>
<TouchableHighlight
underlayColor="rgba(255, 255, 255, 0)"
onPress={this.cardClick}
onLongPress={this.cardLongPress}
onPressOut={this.cardPressOut}
>
{this.content}
</TouchableHighlight>
</View>
</View>
Here is a GIF to show what is happening:
GIF
What I want is something that is only triggered when the user acctually releases his finger, regardless of whether or not he is moving the finger arround. Thanks in advance for the help.
Try setting an offset https://facebook.github.io/react-native/docs/touchablewithoutfeedback#pressretentionoffset , or convert your root view in a touchablewithoutfeedback, and call onPressOut there
So you want an Instagram style preview modal. I got you.
As mentioned in previous comments, you should use the pressRetentionOffset prop that will let you "extend" the pressable area. https://facebook.github.io/react-native/docs/touchablewithoutfeedback#pressretentionoffset
But! this prop will only work if the ScrollView is disabled. so you will need to disable the scrolling when the preview modal is shown.
You can do that with the scrollEnabled prop on ScrollView and make it falsy when the preview modal is shown.
Of course, this works with onLongPress and onPressOut props.

Force focus ReactNative TextInput

I'm having trouble force focussing a react native TextInput field.
It's focused when the page loads with autofocus={true}.
But after blurring I would need to press the text input field, but that's hidden because of design reasons. Is there a way to document.getElementById("myText").focus(); in react native that I can call after onBlur()?
Cheers.
You need to assign the TextInput field to a ref like this:
<TextInput ref={ref => (this.ref = ref)} />
Then you can programmatically focus it by running focus() on it, like so:
this.ref.focus();
Here's a little Snack where I run the focus/blur function when pressing a button:
https://snack.expo.io/#marcelkalveram/auto-focus-input-field-using-ref
It should be easy to replicate this for your navigation scenario.
In case you're using react-navigation, this is the part of the docs you'll be interested in: https://reactnavigation.org/docs/en/navigation-prop.html#addlistener-subscribe-to-updates-to-navigation-lifecycle

Response Delay in react native FlatList

I am using <FlatList> to render a list:
<FlatList
ListFooterComponent={this.renderFooter}
ItemSeparatorComponent={this.renderSeparator}
refreshing={this.state.refreshing}
onRefresh={this.doPullRefresh}
onEndReached={this.endFooter}
initialNumToRender={10}
onEndReachedThreshold={0.5}
removeClippedSubviews={false}
data={this.state.listdata}
renderItem={({item}) => <ListItem onPress={this.goToStuInfo} alldata={item} id={item.key} number={item.number} avatar={item.avatar} name={item.name} />}
/>
The total size of data is about 300. So I can see some data is displayed while other data is being rendered as a list item.
At this moment(some data is still being rendered), if I touch an item, there will be a delay. I have to wait for a long time to get the response. And I have to wait even when I press the Back button.
Is there any solution that the list can response my touch movement first?
My Solution
Well, I solved this problem by render 10 items once.
I will push more data to this.state.listdata in onEndReached
Works for me.
are props change when ya touch items ?? 300 list elements not the big deal
"Limiting the render window also reduces the amount of work that needs to be done by React and the native platform, e.g from view traversals. Even if you are rendering the last of a million elements, with these new lists there is no need to iterate through all those elements in order to render. You can even jump to the middle with scrollToIndex without excessive rendering."