I have a scrollview which has a flatlist nested inside of it, so now I want to scroll to a certain position of the scrollview on button press, how can I achieve this?
Here is my code:
<ScrollView
ref={verticalRef}
>
{
data.map( item => (
<View>
<Text style={styles.title}>{item.title}</Text>
<View >
<FlatList
data={item.data}
numColumns={2}
renderItem={thitem}
/>
</View>
</View>
))
}
</ScrollView>
Here is the handler for the scroll:
const scrollToActiveIndex = (index) => {
setActiveIndex(index)
verticalRef.current?.scrollTo({
x: width * index,
animated: true
})
}
I have also attached a screenshot of my app. Thanksenter image description here
Related
I have two flatLists nested inside of a scrollView so I am able to scroll my entire page. However, I know that you are not supposed to nest flatLists in scrollViews for multiple reasons.
How can I render two flatLists while still being able to scroll throughout the entire page? The GIF at the bottom of the post is the desired behavior I want.
I created a snack post here as well as provided some example code below.
export default function App() {
return (
<View style={{ alignItems: 'center', marginTop: 100, flex: 1}}>
<FlatListB/>
<FlatListA/>
</View>
);
}
return (
<FlatList
data={newData}
renderItem={renderItem}
onEndReached={fetchMoreBars}
onEndReachedThreshold={0.1}
/>
);
return (
<FlatList
data={newData}
renderItem={renderItem}
onEndReached={fetchMoreBars}
onEndReachedThreshold={0.1}
horizontal={true}
/>
);
https://giphy.com/gifs/7V07FvYyn8ZG3nwVVU - This GIF was created by nesting FlatListB and FlatListA in a ScrollView
If you would like to prevent nested flatLists in scrollView, you may use ListHeaderComponent props in FlatList.
FlatListA.js:
<FlatList
data={newData}
renderItem={renderItem}
onEndReached={fetchMoreBars}
onEndReachedThreshold={0.1}
ListHeaderComponent={<FlatListB />}
/>
App.js
export default function App() {
return (
<FlatListA/>
);
}
This should work if 2 flatlists are not scrolling in same direction (Vertical / Horizontal).
try this code
const Data = [1,2,3,4,1,1,1,1,1,1,1,]
const Horizontal = () => {
const Data = [1,2,3,4,1,1,1]
return <FlatList
horizontal
data={Data} renderItem={() => {
return <View style={{height:100,width:100,backgroundColor:'pink',margin:2}}>
</View>
}}/>
}
const ListHeaderComponent = () => {
return <Horizontal/>
}
<View >
<FlatList
ListHeaderComponent={ListHeaderComponent}
data={Data} renderItem={() => {
return <View style={{height:100,width:100,backgroundColor:'white',margin:2}}>
</View>
}}/>
</View>
I have a two part question. I'm currently using react-native-snap-carousel found here: https://github.com/meliorence/react-native-snap-carousel .
My code looks like this:
carouselItems: [
{
image: require('../assets/images/placeholder-slide.png'),
},
{
image: require('../assets/images/slide2.png'),
},
{
//I want to pass <View> here with content and a button
},
]
_renderItem({ item, index }) {
<View>
<Image source={item.image} />
</View>
}
<SafeAreaView style={styles.body}>
<Carousel
layout={"default"}
ref={ref => this.carousel = ref}
data={this.state.carouselItems}
sliderWidth={phoneWidth}
itemWidth={phoneWidth}
renderItem={this._renderItem}
inactiveSlideOpacity={1}
inactiveSlideScale={1}
slideStyle={{ width: phoneWidth }}
onSnapToItem={index => this.setState({ activeIndex: index })} />
//This is the block I want to pass in the 3rd slide of the carousel
<View>
<Text>Some Text Here</Text>
<button>Button here</button>
</View>
</SafeAreaView>
body: {
flex: 1,
position: 'relative',
},
So the first two items in the carousel are a full-width image, the last slide will contain content and 2 buttons. How do I pass the items in the <View> into the carouselItems?
My second question is how do I make the carousel full screen. Here is a screenshot of my simulator: https://ibb.co/ZNZKRqm
As you can see there is grey area above and below the carousel. I don't believe this is something to do with the carousel, I think maybe by default this is full width? But I have seen applications target this gray space as well.
Part
carouselItems: [
{
image: require('../assets/images/placeholder-slide.png'),
},
{
image: require('../assets/images/slide2.png'),
},
{
content:
<View>
<Text>Some Text Here</Text>
<button>Button here</button>
</View>
},
]
_renderItem({ item, index }) {
//return item.content if exists
return item?.content || <View>
<Image source={item.image} />
</View>
}
<SafeAreaView style={styles.body}>
<Carousel
layout={"default"}
ref={ref => this.carousel = ref}
data={this.state.carouselItems}
sliderWidth={phoneWidth}
itemWidth={phoneWidth}
renderItem={this._renderItem}
inactiveSlideOpacity={1}
inactiveSlideScale={1}
slideStyle={{ width: phoneWidth }}
onSnapToItem={index => this.setState({ activeIndex: index })} />
</SafeAreaView>
Part
The grey space is because of theSafeAreaView. This will only be on the devices with a notch. You can set custom backgroundColor for it with a style prop.
I have a flatlist that sends data to another component where the data got filtered, then the flatlist renders the filtered items. I want to get the number of items rendered by the flatlist (i.e the number of remaining items after the data got filtered). How should I do it, please?
Here is the flatlist
<FlatList
style={styles.scrollContainer}
data={this.state.schedules}
keyExtractor={item => item.id.toString()}
horizontal={false}
showsHorizontalScrollIndicator={false}
renderItem={({ item }) => <Today schedule={item} updateSchedule={this.updateSchedule}/>}
keyboardShouldPersistTaps="always"
/>}
And the component that filters the data;
{schedule.once && today == schedule.date ?
<TouchableOpacity
onPress={() => this.toggleScheduleModal()}
>
<View style={[styles.listContainer, {borderLeftWidth: 4}, {borderLeftColor: schedule.color}]}>
<View style={styles.time}>
<Text style={styles.timeText}>{schedule.stime}</Text>
<Text style={styles.timeText}>{schedule.etime}</Text>
</View>
<View style={styles.title}>
<Text style={styles.noteText} numberOfLines={1}>
{schedule.name}
</Text>
<Text style={styles.subtitle} numberOfLines={1}>
{schedule.type}
</Text>
</View>
<View style={styles.day}>
<Text style={styles.subtitle} numberOfLines={1}>
Today
</Text>
<Text style={styles.subtitle} numberOfLines={1}>
{schedule.teacher}
</Text>
</View>
</View>
</TouchableOpacity>
:
[]
}
The data got filtered and is rendered as expected. I just want to know how to count the numbers. Help please.
I believe you could use the method Children.toArray(children) to count how many rendered items there are.
I couldn't figure out where you'd use it in your specific structure, but you'd need to pass the childrenprop to that method. Children, in this case, I believe would be the component you're filtering your data in.
Another option would be to filter the data before rendering you component, which then would just be a matter of getting the array length.
const filterData = () => {
// need to define `today` here
const filteredSchedules = this.state.schedules.filter(schedule => schedule.once && today == schedule.date);
console.log(filteredSchedules.length);
return filteredSchedules;
}
<FlatList
style={styles.scrollContainer}
data={filterData()}
keyExtractor={item => item.id.toString()}
horizontal={false}
showsHorizontalScrollIndicator={false}
renderItem={({ item }) => <Today schedule={item} updateSchedule={this.updateSchedule}/>}
keyboardShouldPersistTaps="always"
/>}
You can try this current rendered index.
onViewableItemsChanged = ({ viewableItems, changed }) => {
console.log("Visible items are", viewableItems);
console.log("Changed in this iteration", changed);
}
<FlatList
onViewableItemsChanged={this.onViewableItemsChanged }
viewabilityConfig={{
itemVisiblePercentThreshold: 50
}}
/>
I wanna know how can I make the action: touch in any item in the list (I'm using FlatList) and show an alert with the position clicked, in React Native - iOS. Follow below, the code must important of my DetailProduct class:
DetailProduct
export default class DetailProduct extends React.Component {
state = {
stores: []
};
componentDidMount() {
this.setState({stores});
}
render() {
return (
<View style={styles.container}>
<FlatList
data={this.state.stores}
showsVerticalScrollIndicator={false}
initialNumToRender={2}
renderItem={({item, index}) =>
<View style={styleItem.container}>
<View style={styleItem.holderImage}>
<Image source={{uri : item.logo_company}} style={{width: '100%', height: '100%'}} resizeMode='contain'/>
</View>
<Text style={item.amount > 0 ? styleItem.textAvailable : styleItem.textUnavailable}>{item.is_available == true ? 'Disponivel' : 'Indisponivel'}</Text>
<TouchableOpacity style={item.amount > 0 ? styleItem.qtdHolder : styleItem.qtdHolderUnavailable} activeOpacity={0.8}>
<Text style={item.amount > 0 ? styleItem.textQtdNum : styleItem.textQtdNumUnavailable}>{item.amount}</Text>
<Image source={require('../imgs/assets/ic_arrow_detail_store.png')} style={item.amount > 0 ? styleItem.icShowDetail : {position: 'absolute', top: -1000}}/>
</TouchableOpacity>
</View>
}
keyExtractor={item => item.id_store}
/>
</View>
);
}
}
You need to wrap your element (the one in your renderItem function) with a TouchableWithoutFeedback or TouchableOpacity element and add the onPress function to the Touchable element. In the onPress function then you can pass the item or index parameter that way you know which position is being clicked and also show the alert.
I have a FlatList in a React Native project. The touchable opacity does register as the view loads, for each row, the console prints selected item.name.. (so, without being touched) however, touching the item does not do anything.
render() {
return(
<FlatList
data={stores.databaseStore.sites.slice()}
keyExtractor={ (item, index) => item.id}
numColumns={1}
extraData={stores.databaseStore.isLoadingSites}
onRefresh={() => this.onRefresh()}
refreshing={stores.databaseStore.isLoadingSites}
renderItem={({item}) => this._renderFlatListItem(item)}
ItemSeparatorComponent={this._renderSeparator}
ListHeaderComponent={this._renderHeader}
ListFooterComponent={this._renderFooter}
/>
)
}
_renderFlatListItem(item) {
return (
<View style={styles.row}>
<TouchableOpacity onPress={this._showSiteDetails(site)}>
<View style={styles.cellLeft} >
<PivotCircle site={item}/>
</View>
</TouchableOpacity>
</View>
)
}
_showSiteDetails(site){
console.log(`selected ${site.name}`);
}
found it with the help of some gents on slack
onPress={this._showSiteDetails(site)}
should be
onPress={ () => this._showSiteDetails(item)}