React native TouchableHighlight ignore the first item - react-native

I have used TouchableHighlight for the FlatList in React native. Here used to display cities which will be returned by an API. But when each item in the flat list is touched only the 1st item is been ignored. But other items except the 1st one get highlighted when I press. Also, I am running the app on my device, not in an emulator. The screenshot of the flatlist
Code
export default class SearchResultsList extends Component {
render() {
return (
(this.props.list &&
<List containerStyle={{ borderTopWidth: 0, borderBottomWidth: 0 }} keyboardShouldPersistTaps={'always'}>
<FlatList
data={this.props.list}
renderItem={({ item }) => (
<TouchableHighlight
onPress={() => {
console.log(item.primaryText);
}}
underlayColor="#cca016"
>
<ListItem
title={item.primaryText}
subtitle={item.secondaryText}
containerStyle={{ borderBottomWidth: 0 }}
/>
</TouchableHighlight>
)}
/>
</List>)
);
}}
When I check without keyboardShouldPersistTaps={'always'} also the same issue is there.

it seems that you're using react-native-elements List component.
If it's the case, you should not place a FlatList inside the react-native-elements List.
Hope it helps

Related

React Native FlatList performance improvements

I'm reading barcodes and every barcode I read I add to an array and show in flatlist. but after 30 barcodes adding to the array getting slow. is there any solution I can do?
renderItem:
const renderItem = useCallback(
({item, index}) => (
<View style={styles.ListItemContainer}>
<Text>
-{item} index: {index}
</Text>
<TouchableOpacity
onPress={() => {
setRemovedItem(index);
setShowAlert(true);
}}>
<Text style={{fontSize: 20, fontWeight: 'bold'}}>X</Text>
</TouchableOpacity>
</View>
),
[],
);
FlatList component:
<FlatList
renderItem={renderItem}
data={barcodeArray}
style={styles.ListContainer}
keyboardShouldPersistTaps="handled"
initialNumToRender={12}
removeClippedSubviews
windowSize={12}
maxToRenderPerBatch={12}
/>
adding barcode:
const readBarcode = barcode => {
setbarcodeArray([barcode, ...barcodeArray]);
setbarcodeValue('');
setkey(key + 1);
};
for this solution you can use VirtualizedList instead Flatlist . In general, this should only really be used if you need more flexibility than FlatList .
for more info see this
Did you try using this: https://github.com/Flipkart/recyclerlistview library. It renders far fewer items than FlatList and then recycles them. Should be must faster and more performant than the native flatlist. If this does not work then try to use getItemLayout in flatlist if you have a fixed height of the content.

ERROR - VirtualizedLists should never be nested inside plain ScrollViews with the same orientation

I'm working on a react-native app and I have to put a list of object in a Scrollview, so I use the FlatList component to do it. This is the piece of code that generates the error:
<ScrollView contentContainerStyle={style}>
Other components
<FlatList
style={style}
data={data}
scrollEnabled={false}
keyExtractor={(item, index) => index.toString()}
renderItem={({ item, index}) => (somethings)}
/>
Other components
</ScrollView>
The complete error is: VirtualizedLists should never be nested inside plain ScrollViews with the same orientation because it can break windowing and other functionality - use another VirtualizedList-backed container instead.
Avoid using FlatList with the same orientation. Instead, restructure your code like this --
<ScrollView contentContainerStyle={style}>
Other components
{
data.map((item)=> <Somthing item={item}/>)
}
Other components
</ScrollView>
Flatlist has its own ScrollView you can scroll through the list using that so there is no need to put a flatlist into a ScrollView that is why its giving a warning, the both scrollview will clash and one of them (mostly the parent one) works.
The error is self explanatory and it should be in a developers best interest to avoid these kind of things even when it's just a false alarm.
Your particular situation could use the following solution:
<FlatList
data={data}
keyExtractor={(item, index) => `key-${index}`}
ListHeaderComponent={() => (
<SomeComponents>
...Some components those need to be on top of the list
</SomeComponents>
)}
ListFooterComponent={() => (
<SomeComponents>
...Some components those need to be below the list
</SomeComponents>
)}
renderItem={({ item, index}) => (somethings)}
/>
Another note, if you need more complex list that needs header and footer for the list itself, you can try SectionList.
Your component FlatList and ScrollView have the same orientation(vertical), so you need put your component inside a ScrollView with horizontal orientation like this:
<View>
<ScrollView nestedScrollEnabled={true} style={{ width: "100%" }} >
<View>
<ScrollView horizontal={true} style={{ width: "100%" }}>
<FlatList />
</ScrollView>
</View>
</ScrollView>
</View>
Solution 1: Use FlatList props ListHeaderComponent and create all of your page top section in that. Something like this:
This will not show any warning or error.
Solution 2:
Because only parent view will scroll (ScrollView) and not the child FlatList, so to get rid of the warning you can pass a prop scrollEnabled={false} to the FlatList.
If it doesn't go then import LogBox from react-native and write this in your component
useEffect(() => {
LogBox.ignoreLogs(["VirtualizedLists should never be nested"])
}, [])
hopefully, the warning will be removed.
Anyone want to solve this issue can use a custom VirtualizedScrollView like this:
import React from 'react';
import { FlatList } from 'react-native';
const VirtualizedScrollView = props => {
return (
<FlatList
{...props}
data={[]}
keyExtractor={(e, i) => 'dom' + i.toString()}
ListEmptyComponent={null}
renderItem={null}
ListHeaderComponent={() => (
<>{props.children}</>
)}
/>
);
};
export default VirtualizedScrollView;
Then if you use FlatList inside VirtualizedScrollView, it won't get the warning/error.
<VirtualizedScrollView>
<FlatList
/*--- your props ---*/
/>
</VirtualizedScrollView>
There is a npm package where I get this code, you can also use this package
Solution:
I have also encountered same problem with FlatList. Then the package below solved my problem.
'react-native-virtualized-view'
import { ScrollView } from 'react-native-virtualized-view'
if ScrollView is Vertical change Flatlist Horizontal
<ScrollView >
<FlatList
horizontal
data={lenders}
keyExtractor={(_, index) => index}
renderItem={(item) => {
return <Text>item</Text>
}}
/>
You can solve the 2 vertical ones(I'm assuming their side by side, separated with a segemented control?) by using the same flat list and switching out the data when it's switched. If they're just two vertical flat list's one after another use the SectionList.
For the horizontal one you can try putting the Horizontal FlatList in the ListHeaderComponent of the vertical FlatList and see what happens. It can be janky if you use a vertical FlatList in a vertical scroll view but maybe with two different axis it might be ok. The other option is two only show a few items in the horizontal scrollview and have a "Show More".
The last option is too re design/rethink the page so it's not doing so much. On mobile less is more and developers/designers like to get in the mindset of porting desktop thinking onto mobile. Might be worth a shot.
I used the SectionList approach to solve this & wanted to post a code example because I found the Section data required by React Native to be clear but also quite prescriptive.
renderList = ({empty, posts}: {empty: boolean, posts: Array<Object>}) => (
<SectionList
sections={[
{type: 'MAP', data: [{}]}, // Static sections.
{type: 'PROFILE', data: [{}]},
{type: 'POSTS', data: posts} // Dynamic section data replaces the FlatList.
]}
keyExtractor={(item, index) => index}
renderItem={({item, section}) => {
switch (section.type) {
// Different components for each section type.
case 'MAP':
return <MapView />;
case 'PROFILE':
return <Profile />;
case 'POSTS':
return <Post item={item} />;
default:
return null;
}
}}
ItemSeparatorComponent={() => <Separator />}
ListFooterComponent={() => <>{empty && <EmptyList />}</>}
/>
);
What's nice is that the content feels logically quite separate, so you can add sections easily or have different dynamic data sources.
(If you're building a form & want better keyboard handling, you could also try a KeyboardAwareSectionList from react-native-keyboard-aware-scroll-view.)
Flatlist has an integrated scrollview itself, so you can resolve this error by removing ScrollView Component, And let just the Fatlist component
Error ? you are trying to render a FlatList component inside a scrollview component, this is what is throwing the warning.
solution Render the components using Flatlist's ListHeaderComponent={} prop, i.e in your flatlist add the prop as follows
const FlatList_Header = () => {
return (
<View style={{
height: 45,
width: "100%",
backgroundColor: "#00B8D4",
justifyContent: 'center',
alignItems: 'center'
}}
>
<Text style={{ fontSize: 24, color: 'white' }}> Sample FlatList Header </Text>
</View>
);
}
<FlatList
data={BirdsName}
renderItem={({ item }) => <ItemRender name={item.name} />}
keyExtractor={item => item.id}
ItemSeparatorComponent={ItemDivider}
**ListHeaderComponent={FlatList_Header}**
ListHeaderComponentStyle={{ borderBottomColor: 'red', borderBottomWidth: 2 }}
/>
Note the use of the ListHeaderComponent in the code above, that should supress the warning.
Use flatList like this ListHeaderComponent and ListFooterComponent:
<FlatList ListHeaderComponent={
<ScrollView
style={styles.yourstyle}
showsVerticalScrollIndicator={false}
>
<View style={styles.yourstyle}>
</View>
</ScrollView>
}
data={this.state.images}
renderItem={({ item, index }) => {
return (
<View
style={styles.yourstyle}
>
<Image
source={{
uri: item,
}}
style={styles.yourstyle}
resizeMode={"contain"}
/>
<Text
numberOfLines={2}
ellipsizeMode="tail"
style={styles.yourstyle}
>
{item.name}
</Text>
</View>
);
}}
keyExtractor={({ name }, index) => index.toString()}
ListFooterComponent={
<View style={styles.yourstyle}></View>
}
/>
In my case it was happening due to nesting of ScrollView.
Try replacing some of the ScrollView from children components with React.Fragment.
The solution is very simple, please do not put the Flatlist component in the ScrollView.
They both have the same functionality but Flatlist has advantages and is more stable to use.

How to prevent flatlist header or footer from re-render in reactnative

I put an input field in the footer of flatlist but when i try to type anything it dismiss the keyboard automatically because of the re-render of the flatlist footer..
I tried to nest the flatlist from Scrollview but this brings warning..
How can i stop the footer from being re-rendered? can i fix this without nest the flatlist from Scrollview?
<FlatList
ListHeaderComponent={() => (
<View style={styles.discountContainer}>
<Text style={[styles.buttonText, { letterSpacing: 3 }]}>
10% DISCOUNT ON 8 COURSES
</Text>
</View>
)}
numColumns={2}
data={data}
renderItem={({ item }) => (
<View>
<SingleProduct item={item} />
</View>
)}
ListFooterComponent={() => (
<View>
<View style={styles.couponContainer}>
<Input
placeholder='Coupon code'
placeholderTextColor='#0a5796'
color='#0a5796'
inputStyle={{
color: '#0a5796',
}}
inputContainerStyle={{
borderBottomWidth: 0,
height: 50,
}}
containerStyle={styles.couponInputContainer}
onChangeText={(value) =>
this.setState({ couponCode: value })
}
value={this.state.couponCode}
/>
{couponLoading ? (
<View style={styles.couponButton}>
<ActivityIndicator />
</View>
) : (
<TouchableOpacity
style={styles.couponButton}
onPress={() => this.codeCheck(couponCode, line_items)}
>
<Text style={styles.buttonText}>Apply Coupon</Text>
</TouchableOpacity>
)}
</View>
</View>
)}
/>
Arrow-Funktions are "always" executed and create a new Reference in Memory. This way they will always re-rendering if component will be executed.
For performance reasons you better define your function outside and call it like this:
function renderMyItem(){ ...bimbom... yous stuff goes here! }
function renderHeader(){ ...bimbom... yous stuff goes here! }
<Flatlist
renderItem={this.renderMyItem()}
ListHeaderComponent={this.renderHeader()}
...
/>
What happens here?
Both of your functions renderMyItem and renderHeader will be executed once if your component is loaded and will be saved in memory. So every time you call one of the functions, you call a reference to the place in memory where they are saved.
In the other case, Arrow-Functions ()=>{...} are executed in current context and generate a new reference in Memory, each time they called, because .. to say it clear: you define & call a function that way.
If you are using Functional Component then don't use Arrow function () => (...) for header and footer components of FlatList but instead only return your header and footer Components as shown in the sample below.
<FlatList
...
ListHeaderComponent={(<View><Text>Header</Text></View>)}
ListFooterComponent={(<View><Text>Footer<Text></View>)}
/>
I was going through the same problem and the accepted answer didn't worked for me. As here the problem occurs because we are updating the state whenever the text changes (as defined in onChangeText) which causes re-rendering. Thus i came up with another solution;
First i created another dict object newState which has nothing to do with state or props. So on changing newState dict, it will not cause re-rendering. Then;
newState = {}
<TextInput onChangeText={text => this.newState.value = text} />
Then i changed the state(which is necessary as per your problem and as per mine) on onEndEditing ;
<TextInput onChangeText={text => this.newState.value = text} onEndEditing={this.setSearch} />
Here is setSearch
setSearch= () => {
this.setState({couponCode: this.newState.value})
delete this.newState.value;
}
I am deleting the key after the state is set because it doesnot update correctly next time.

Flatlist + React Native Router Flux: slow navigate transition

I have a datasource with more than 800 entries which I'm using FlatList to render it.
Each renderItem receives a function to navigate to another screen on item press.
The problem is that the transition between screens is extremely slow.
I noticed that even with scrolling working fast, renderItem is still being called for all 800 entries in DOM. When all items are finally rendered, then the navigation works fine.
I've tried using initialNumToRender, getItemLayout and waitForInteraction props, as well tried to change my renderItem component (now is a stateless component) to a pure component. Nothing seems to work so far.
Any suggestion will be appreciated.
Here's some code if may help:
<FlatList
data={this.state.listDataSource}
renderItem={({ item, index }) => this.renderListItem(item, index)}
keyExtractor={this._keyExtractor}
style={{
flex: 1,
marginHorizontal: 30,
borderTopWidth: 1,
borderColor: '#919191',
}}/>
renderListItem(item, index) {
return <ListItem dotFunc={() => this.onListItemPress(index)} item={item} />;
}
onListItemPress(index) {
Actions.itemDetail({
index
});
}
// ListItem.js correctly exported
const ListItem = ({ dotFunc, item }) => (
<TouchableOpacity onPress={() => Actions.contactDetail({rowID})}>
<Text>{Item}</Text>
</TouchableOpacity>
}
Thanks

React Native: Refreshing gets stuck while scrolling in nesting FlatLists in Androdid

While using a horizontal FlatList with other vertical FlatList as items there seems to be an issue with the refreshing. This happens when refreshing is enabled on the vertical lists but not on the horizontal container list. It is actually possible to refresh each individual list if you are very carful and only scrolls vertically (this is very hard). But at once you scrolls sideways the refreshing gets stuck.
React Native nested FlatLists
Issue in Android. Works in iOS
Attempts
I have tried replacing the wrapping FlatList with a ScollView with the same result. I am fully aware of that it is possible to disable refreshing of the individual list and enable it on the containing FlatList but that is not very appropriate in my case.
I have also tried the upvoted answers on this similar question but it didn't solve it.
Example:
<FlatList
horizontal={true}
pagingEnabled={true}
data={[{key: 'a'}, {key: 'b'}]}
renderItem={({item}) =>
<FlatList
style={{width: 400}}
ref="scrollView"
horizontal={false}
refreshing={false}
onRefresh={() => {}}
data={[{key: 'c'}, {key: 'd'}]}
renderItem={({item}) => <Text>{item.key}</Text>}
/>
}
/>
Does anyone have a solution to this?
ScrollView/ Flatlist import from react-native-gesture-handler can be stuck refresh when released outside of the screen. Use ScrollView import from react-native
i created a component based on what i understood from ur question,
make second flat list width as u want and put the height as '100%' so it will com full screen, so that it behaves like paging 2 flat lists... Hope it works for u
Here is the code
Snack URL
import React, {Component} from 'react';
import {
View,
Text,
Image,
TouchableOpacity,
FlatList,
Dimensions,
} from 'react-native';
const { width } = Dimensions.get('window');
export default class App extends Component {
render() {
return (
<View style={{ flex: 1 }}>
<FlatList
horizontal
pagingEnabled
data={[{ key: 'a' }, { key: 'b' }]}
renderItem={({ item }) => (
<FlatList
style={{ width, height: '100%' }}
// ref="scrollView"
horizontal={false}
refreshing={false}
onRefresh={() => {}}
data={[{ key: 'c' }, { key: 'd' }, { key: 'f' }, { key: 'h' }]}
renderItem={({ item }) => (
<Text style={{ paddingVertical: 40 }}>{item.key}</Text>
)}
/>
)}
/>
</View>
);
}
}