React-Native horizontal FlatList - react-native

I have flat list that is returning a JSON feed with nested objects / arrays. All is working except horizontal listing, it still lists each item vertically. Does anyone know how I can list the returned images horizontally instead of vertically?
{isLoading ? <ActivityIndicator/> : (
<FlatList
data={[data]}
horizontal={true}
keyExtractor={({ id }, index) => id}
renderItem= {({ item, index }) => (
<View>
{item.items.map((v, i) => (
<TouchableOpacity onPress={() => props.navigation.navigate('Pdp', {articleid: item.id})}>
<View style={styles.container}>
<Image style={styles.imgyoutubeprev} source={{ uri: chkValue(v.snippet.thumbnails.high.url) }} />
<Image style={styles.imgyoutubebtnoverlay} source={require('../assets/youtubebtn.png')} />
</View>
</TouchableOpacity>
))}
</View>
)}
/>
)}

We would need to have a bit more information about the styles that you are using. If the items are rendered vertically instead of horizontal then this is likely caused by the element that surrounds the FlatList.
Make sure that the View or other component that contains the FlatList has the flex: 1 style or at least takes up the full width. Otherwise the horizontal elements would still wrap and be rendered vertically.
Bonus tip: You might be able to remove the View child from the TouchableOpacity by moving the styles.container to the TouchableOpacity and then replacing the inner View with a Fragment.

Thanks all. The big difference was removing the view surrounding the item.items.map. I haven't had to force flex: 1 against the view, though I have forced flex 1 across the whole screen, so possibly thats helped as well. Thanks again all.
The code I used (taking on your code reduction, and is working as expected is;
return (
<View>
{isLoading ? <ActivityIndicator/> : (
<FlatList
data={[data]}
horizontal={true}
horizontal
keyExtractor={({ id }, index) => id}
renderItem= {({ item, index }) => (
item.items.map((v, i) => (
<TouchableOpacity onPress={() => props.navigation.navigate('Pdp', {articleid: item.id})}>
<Image style={styles.imgyoutubeprev} source={{ uri: chkValue(v.snippet.thumbnails.high.url) }} />
<Image style={styles.imgyoutubebtnoverlay} source={require('../assets/youtubebtn.png')} />
</TouchableOpacity>
))
)}
/>
)}
</View>
);
};

Related

Aligning ListHeaderComponent vertically above Horizontal Flatlist

I have a horizontal Flatlist and right above it i want to add a custom header. I have an option to wrap the Flatlist & custom header in a ScrollView - which isn't good practice according to RN 0.61
VirtualizedLists should never be nested inside plain ScrollViews with
the same orientation
Another option is to use:
ListHeaderComponent
<FlatList
horizontal
ListHeaderComponent = {<CustomHeader>What can we help you find?</CustomHeader> }
keyExtractor = {(item) => item.unique_id }
data = {this.props.categories}
contentContainerStyle={{ flexGrow: 1}}
renderItem={ ({item}) => (
<TouchableOpacity>
<View>
<Image
style={{
height:80,
width:100}}
source={{uri:'some_url'}}
/>
<Title>{item.category}</Title>
</View>
</TouchableOpacity>)}
/>
Whilst the above works with a vertical Flatlist, it completely fails with a horizontal flatlist with my use case.
Expected:
Actual Output:
What are the possible fixes?
You can Conditional Rendering like this, just a workaround
{this.props.category.length ? <CustomHeader>What can we help you find?</CustomHeader> : null}
<FlatList
horizontal
keyExtractor = {(item) => item.unique_id }
data = {this.props.categories}
contentContainerStyle={{ flexGrow: 1}}
renderItem={ ({item}) => (
<TouchableOpacity>
<View>
<Image
style={{
height:80,
width:100}}
source={{uri:'some_url'}}
/>
<Title>{item.category}</Title>
</View>
</TouchableOpacity>)}
/>

react native - I cannot scrolling down with two flatlist

I can scroll only in case when I change SafeAreaView to ScrollView but I get this error
VirtualizedLists should never be nested inside plain ScrollViews with the same orientation - use another VirtualizedList-backed container instead.
{subCategoryIsLoading ? (
<ActivityIndicator
size='large'
color={primColor}
style={{marginTop: 150}}
/>
) : (
<SafeAreaView>
<View style={styles.containerSubCategory}>
<FlatList
showsVerticalScrollIndicator={false}
data={filterCatTrue()}
keyExtractor={item => item._id}
renderItem={({item}) => {
return (
<View style={styles.containerImages}>
<TouchableHighlight onPress={() => console.log(item._id)}>
<Image
source={{
uri: `${urlImages}subCategories/${item.image}`,
}}
style={styles.imageSubCategory}
/>
</TouchableHighlight>
</View>
)
}}
/>
<FlatList
horizontal={false}
numColumns={2}
showsVerticalScrollIndicator={false}
columnWrapperStyle={{
justifyContent: 'space-between',
}}
data={filterCatFalse()}
keyExtractor={item => item._id}
contentInset={{bottom: 60}}
renderItem={({item}) => {
return (
<View style={styles.containerImagesWide}>
<TouchableHighlight>
<Image
source={{
uri: `${urlImages}subCategories/${item.image}`,
}}
style={styles.imageSubCategoryWide}
/>
</TouchableHighlight>
</View>
)
}}
/>
</View>
</SafeAreaView>
)}
Virtualized lists, that means 'SectionList' and 'FlatList' for example, are performance-optimized meaning they improve memory consumption when using them to render large lists of content. The way this optimization works is that it only renders the content that is currently visible in the window, usually meaning the container/screen of your device. It also replaces all the other list items same sized blank space and renders them based on your scrolling position.
Now If you put either of these two lists inside a ScrollView they fail to calculate the size of the current window and will instead try to render everything, possibly causing performance problems, and it will of course also give you the warning mentioned before.
Check this post, it perfectly explains your problem.

Can't use both Scrollview and Flatlist within same React Native component

I'm trying to use a Scrollview to scroll horizontally a mapped array and also a Flatlist to scroll vertically a list of items from another array but the combination of the 2 don't seem to work.
This is not a case on wrapping a Flatlist inside a Scrollview which causes a well known problem, I'm not getting the VirtualizedLists warning here.
Here's my code in the rendering section:
return (
<View style={styles.screen}>
<Scrollview style={styles.containerRow}>
{selectedGenres.map((item) => {
return (
<TouchableOpacity
onPress={() => {
genreHandler(item.id, item.name);
}}
style={styles.containerRow}
key={item.id}
>
<View style={styles.filterGenderLayout}>
<Text style={styles.genderButton}>{item.name}</Text>
</View>
</TouchableOpacity>
);
})}
</Scrollview>
<View style={styles.container}>
<View style={styles.containerRow}>
<FlatList
numColumns={3}
data={result}
keyExtractor={(item) => item.id.toString()}
onEndReached={loadMoreCommit}
onEndReachedThreshold={0.5}
renderItem={(itemData) => (
<StarsItem
id={itemData.item.id}
poster={itemData.item.poster_path}
title={itemData.item.title}
onStarsSelection={fetchMovieHandler}
showtitle={false}
/>
)}
/>
</View>
</View>
</View>
As you can see the Scrollview and Flatlist are not nested but I get an error as invalid element. If I use a normal View tag instead of Scrollview, everything looks fine except that I cannot scroll my first list horizontally.
Any suggestion on how to fix this?
I tried to use Flatlist on both however I need the first to scroll horizontally and the second vertically with numColumns={3} meaning I get a different error.

Last item in React native flat list goes beyond screen

I have a flatlist with some styles on the outer containers as follows.
<View style={containerStyle}>
// more jsx components come here
<View style={resultContainerStyle}>
<FlatList
data={results}
keyExtractor={(item) => (item.id && item.id.toString())}
renderItem={({ item, index }) => (
<ListItem
item={item}
selectItem={selectItem}
/>
)}
/>
</View>
</View>
The issue is that the last values of the list go beyond the view of the screen and there is no way to view it unless a fixed height is put on the parent container. Is it possible to do this without a fixed height.
A SafeAreaView can be used to limit the view to the "safe" areas of the screen(avoiding the notch and curved bottom. Checkout the following example
<SafeAreaView style={containerStyle}>
// more jsx components come here
<View style={resultContainerStyle}>
<FlatList
data={results}
keyExtractor={(item) => (item.id && item.id.toString())}
renderItem={({ item, index }) => (
<ListItem
item={item}
selectItem={selectItem}
/>
)}
/>
</View>
</SafeAreaView>
more examples can be found at the react native docs.

React Native FlatList not scrolling to end

I've got (what I thought was) a simple FlatList which renders a list of Cards (code below)
Problem: the list renders, but won't scroll to fully display the last element in the list, OR to the content below the FlatList
What I've tried: basically everything in related SO questions:
Removing ALL styling
Wrapping the FlatList in a View or a ScrollView or both
Adding style={{flex: 1}} to the FlatList or wrappers (this causes **ALL* content to disappear)
Any ideas?
<FlatList
data={props.filteredProducts}
renderItem={({item}) => (
<TouchableOpacity onPress={() => props.addItemToCart(item)}>
<Card
featuredTitle={item.key}
image={require('../assets/icon.png')}
/>
</TouchableOpacity>
)}
keyExtractor={item => item.key}
ListHeaderComponent={
<SearchBar />
}
/>
...
<Other Stuff>
Add style={{flex: 1}} for each View element who is a parent for FlatList.
I had the same issue and just found the solution. Add the prop ListFooterComponentby giving it a React element/component. I just passed a view with the preferable height and it worked for me perfectly.
Here is the code snippet:
<FlatList
data={DATA}
renderItem={({ item }) => (<ListItem itemData={item} />) }
keyExtractor={item => item.id}
ListFooterComponent={<View style={{height: 20}}/>}
/>
This works 100%!
The ultimate solution is ✔
Any view/subview that holds a flatlist must have a flex of 1 - Regardless of how deep.
So if you apply this and it's not working, check your styling and make sure there's no mistake somewhere.
I'm not sure if your scenario is exactly the same as one I encountered on a project a few months ago, but I noticed that I had to add a margin/padding (depends on what you prefer) to lift the bottom of the scrollable container. This was usually because a parent container seemed to interfere with the styling of the scrollable element.
Have you tried adding flexGrow: 1 to your styling in place of flex?
My case is a little different, in that I used FlatList inside bottom sheet provided by reanimated-bottom-sheet package. But the problem was the same: scrolling didn't show the last item properly.
The way I did was I calculated and set the height of the view that included the FlatList. To make it look better when there is bottom inset, I gave more bottom margin to the last item of the FlatList by doing like this:
<FlatList
data={results}
keyExtractor={(item) => item.name}
scrollEnabled={bottomSheetIndex == 1 ? true : false}
renderItem={({ item }) =>
<LocationInfo
bottom={results[results.length - 1].id == item.id ? insets.bottom : 0}
result={item}
wait={waitState[item.id]}
bsIndex={bottomSheetIndex}
/>
}
/>
const LocationInfo = ({ bottom, result, wait, bsIndex }) => {
return (
<View style={[styles.container, { paddingBottom: bottom }]}>
...
for insets, see react-native-safe-area-context.
Remove flex:1 from the FlatList and leave only the parent View.
Add flex: 1 to child into renderItem
<View style={{ height: `93%` }}>
<FlatList
contentContainerStyle={{ minHeight: `100%` }}
scrollEnabled={true}
...props
renderItem={({item}) => (
<View style={{ flex: 1 }}>
...
</View>
)}
I had the same problem. What I did was to provide a marginBottom to the parent view of the FlatList with size that is equivalent (or a little larger) than the size of the rendered item .
<View style={{marginBottom: HEIGHT_OF_CELL + 60, flexGrow:1}}>
<FlatList
keyExtractor={(item, index) => index.toString()}
data={posts}
renderItem={renderItem}
/>
</View>
I method I used to resolve this is by setting the parent view to the FlatList's background color to a visible color(e.g red). Then adjust the margin bottom for that view so that it is large enough for all the contents in the FlatList to be viewed.
In my case the parent view was wrapped in another view which I could not give the flex: 1 style to.
use dimensions for parent view and set height as given:
const screenHeight = Dimensions.get('window').height - 100
<View style={{...styles.container,height:screenHeight}}>
....All child components
</View>
adding flex:1 to my render item worked for me
<FlatList
data={data}
renderItem={({ item }) => (
<ListItem
onPress={() => console.log('ok')}
bottomDivider
rightTitle={
<Divider style={{ marginBottom: 4, backgroundColor: item.status, width: '50%', height: '11%', borderRadius: 10 }} />
}
titleProps={{ numberOfLines: 1 }}
rightSubtitle={item.date}
rightTitleStyle={{ fontFamily: 'poppins' }}
rightSubtitleStyle={{ fontFamily: 'poppins' }}
titleStyle={{ fontFamily: 'poppins' }}
subtitleStyle={{ fontFamily: 'poppins' }}
title={item.device}
subtitle={item.type}
leftAvatar={{ source: item.icon, rounded: false }}
**style={{ flex: 1 }}**
/>
)}
keyExtractor={item => item._id}
ListHeaderComponent={renderHeader}
ListFooterComponent={renderFooter}
onEndReached={handleLoadMore}
onEndReachedThreshold={0.2}
/>