Aligning ListHeaderComponent vertically above Horizontal Flatlist - react-native

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>)}
/>

Related

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

I'm building a mobile application with React Native, and I have a ScrollView inside one of the pages.
The problem is that I have in this page a FlatList so when I go to that page, I get this error:
VirtualizedLists should never be nested inside plain ScrollViews with the same orientation... The thing is, I set the ScrollView nestedScrollEnabled to true and I also set the FlatList's scrollEnabled to false because I don't really need the scroll there (I'm using it to render items from an enum) so I thought that should fix the error, but the error still persist.
It looks like this:
<ScrollView showsVerticalScrollIndicator={false} nestedScrollEnabled={true}>
<MyComponent />
</ScrollView>
And MyComponent has this FlatList:
<FlatList
scrollEnabled={false}
style={{padding: 8,marginBottom: 8,}}
data={categories}
numColumns={numOfColumns}
keyExtractor={category => category}
renderItem={item => renderItem(item.item)}
/>
It essentially looks like this:
<SafeAreaView>
<ScrollView>
<FlatList />
<OTHER COMPONENTS />
</ScrollView>
</SafeAreaView>
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%" }}>
<MyComponent />
</ScrollView>
</View>
</ScrollView>
</View>
The error is because you are using a FlatList inside a ScrollView.
The FlatList is already a scrollable component,
FlatList are accepting props like ListHeaderComponent for rendering header content and ListFooterComponent for rendering footer content. Here you can remove the ScrollView and instead of that you can only render FlatList for making whole page scrollable
You need to change your code as shown below:
const _renderHeader = () => <Text>Your Header</Text>
const _renderFooter = () => <Text>Your Footer</Text>
const _renderFooter = () => <Text>FlatList items</Text>
<SafeAreaView>
<FlatList
data={data}
keyExtractor={(item, index) => String(index)}
renderItem={_renderItem}
ListHeaderComponent={_renderHeader}
ListFooterComponent={_renderFooter}
ListFooterComponentStyle={styles.footerStyle} //If you need to give specific styles for footer component
ListHeaderComponentStyle={styles.headerStyle} //for header comp style
/>
</SafeAreaView>
You don't want to use a ScrollView when you are using a FlatList
You can check the official docs for more clarification

Horizontal scrolling in FlatList - React Native

I'm listing data with flatlist. But while listing the data, it lists it vertically, I want it to be sorted horizontally. So instead of scrolling down, I want to scroll left and right. I think it's called pagingEnabled. How can I do that?
<FlatList
style={{
flex: 1
}}
showsVerticalScrollIndicator={false}
showsHorizontalScrollIndicator={false}
data={this.state.allReasons}
keyExtractor={(item,index)=>index.toString()}
renderItem={({ item ,index}) => {
return (
<ScrollView onScroll={(event)=>{
this.setState({
activePage:Math.round(parseFloat(event.nativeEvent.contentOffset.x/Dimensions.get('window').width))
})
}}
style={{width:'100%'}} showsHorizontalScrollIndicator={false} pagingEnabled={true} horizontal={true}>
<View style={{width:'100%'}}>
<Image style={{ resizeMode: 'contain',width:Dimensions.get('window').width,height:250}} source={{uri:"http://ledslider.stechomeyazilim.com/" + item.Slider_Image}}/>
.....
</View>
Add horizontal prop in Flatlist like
horizontal={true}
Try removing scrollview from item may cause the issue

React-Native horizontal FlatList

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>
);
};

react-native : horizontal scrollview won't work inside flatlist

I have a horizontal scrollview inside my flatlist but it won't scroll.
renderRow = ({ item }) => {
return (
<View style={{width:'100%', backgroundColor:'transparent'}}>
<ScrollView horizontal={true}>
//I have multiple images here
</ScrollView>
</View>
)
}
This is my flatlist
<FlatList
keyExtractor={(item, index) => index.toString()}
data={this.state.data}
renderItem={this.renderRow}
/>
is it possible to put horizontal scrollview inside flatlist?
Try to add style width:100% in ScrollView
<ScrollView horizontal={true} style={{width:'100%'}}>
//I have multiple images here
</ScrollView>
You can try somethig like this:
<ScrollView horizontal={true} style={{flex: 1}}>
//Place Mutiple image in ScrollView.
</ScrollView>

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}
/>