I'm new in react-native. On one of my screen I'm using flatlist on 4 places but the last flatlist which is displaying at the bottom of screen is not scrolling so I add the scrollView then its working fine but displaying me that error
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.
code
const Header = () => {
return (
<View>
<SafeAreaView>
<View style={styles.sellersheaderWrapper}>
<View style={styles.sellersheaderTitle}>
<Text style={styles.sellersheaderTitleText}>
Featured Sellers
</Text>
</View>
<View>
{
isFeatureSeller == '' ?
<View style={[styles.noSpecialOfferCard, {paddingVertical:hp('2%')}]} >
<Text style={[styles.noSpecialOfferCardText, {fontSize:hp('2%')}]}>Currently, No Feature Sellers</Text>
</View>
:
<View>
<FlatList
data={isFeatureSeller}
renderItem={renderCategoryItem}
keyExtractor={item => item.id}
horizontal={true}
showsHorizontalScrollIndicator={false}
/>
</View>
}
</View>
</View>
</SafeAreaView>
<View style={styles.searchWrapper}>
<View style={styles.dobregisterFormWrapperText}>
<TextInput
style={styles.dobregisterInputStyleText}
value={search}
onChangeText={(text) => searchFilterFunction(text)}
onClear={(text) => searchFilterFunction('')}
placeholder="Search ..."
/>
<View>
<SearchIconSvg />
</View>
</View>
</View>
</View>
);
};
const Footer = () => {
return (
<View>
<View style={styles.specialOfferCardWrapper}>
<View style={styles.specialOfferCardTextWrapper}>
<Text style={styles.specialOfferCardText}>Special Offer Cards</Text>
</View>
{isSpecialCards == '' ? (
<View style={styles.noSpecialOfferCard}>
<Text style={styles.noSpecialOfferCardText}>
No Special Offer cards
</Text>
</View>
) : (
<FlatList
data={isSpecialCards}
renderItem={renderCards}
keyExtractor={(item, index) => index.toString()}
horizontal={true}
showsHorizontalScrollIndicator={false}
style={styles.specialCards}
/>
)}
<View
style={[
styles.specialOfferCardTextWrapper,
{paddingBottom: isFeatureSeller == '' ? hp('17%') :hp('10%') },
]}>
<Text style={styles.specialOfferCardText}>Cards</Text>
<FlatList
data={isCard}
renderItem={renderNormalCards}
keyExtractor={item => item.id}
showsVerticalScrollIndicator={false}
scrollEnable={true}
/>
</View>
</View>
</View>
);
};
const MainData = () => {
return(
<View>
{search == '' ? (
<ScrollView>
<View >
<Header />
<Footer />
</View>
</ScrollView>
) : (
<View >
<FlatList
data={filteredDataSource}
renderItem={renderCategoryItemSearch}
keyExtractor={(item, index) => index.toString()}
ListHeaderComponent={Header}
/>
</View>
)}
</View>
)
}
return (
<View style={styles.container}>
{
loading == true ?
<View style={{marginVertical:hp('45%')}} >
<ActivityIndicator size="large" color={colors.primary} />
</View>
:
<MainData/>
}
<View style={styles.bottomNavWrapper}>
<TouchableOpacity
style={styles.storeWrapper}
onPress={() => navigation.navigate('BuyerDashboard')}>
<View style={styles.storeIcon}>
<DashboardReverseSvg />
</View>
</TouchableOpacity>
<View style={styles.dashboardWrapper}>
<View style={styles.dashboardIcon}>
<BuyerStoreReverseSvg />
</View>
<View style={styles.dashboardText}>
<Text style={styles.dashboardTextfont}>Storefront</Text>
</View>
</View>
</View>
</View>
);
};
export default Store;
I want to scroll at here.
<ScrollView>
<View >
<Header />
<Footer />
</View>
</ScrollView>
You can use nestedScrollEnabled prop on your FlatList component
https://reactnative.dev/docs/scrollview#nestedscrollenabled
Related
How to make Flatlist render Text, View elements? In rn, I am currently using scroll view, but I want to test flatlist I read rn docs to know about it, but I can't render text view elements with their styles, Can anyone tell how to do that in a proper way? I just want to use flatlist instead of scroll view
Elements that I want to render:
<View style={styles.section1}>
<Image style={styles.profileimg} source={{ uri: data.profilepic }} />
<Text style={styles.usernameText}>#{data.username}</Text>
<View style={styles.Postrow}>
<View style={styles.Postrow1}>
<Text style={styles.followerTxt}>UpVotes</Text>
<Text style={styles.UpVote}>{data.upvotes}</Text>
</View>
<View style={styles.verticalLine}></View>
<View style={styles.Postrow1}>
<Text style={styles.followerTxt}>DownVotes</Text>
<Text style={styles.UpVote}>{data.downvotes}</Text>
</View>
<View style={styles.verticalLine}></View>
<View style={styles.Postrow1}>
<Text style={styles.followerTxt}>Posts</Text>
<Text style={styles.UpVote}>{data.post.length}</Text>
</View>
</View>
<Text style={styles.decs}>Hello this is des</Text>
</View>
<View style={styles.section1}>
<Text style={styles.postTxt}>Your Posts</Text>
<View style={styles.posts}>
{
data.post.map((item) => {
return (
<Image key={item.id} style={styles.Postimage} source={{ uri: item.postimg }} />
)
})
}
</View>
</View>
you need to use the renderItem prop with FlatList
first create function component to pass it to the renderItem prop:
const renderItem = (item) => (
<View style={styles.section1}>
<Image style={styles.profileimg} source={{ uri: data.profilepic }} />
<Text style={styles.usernameText}>#{data.username}</Text>
<View style={styles.Postrow}>
<View style={styles.Postrow1}>
<Text style={styles.followerTxt}>UpVotes</Text>
<Text style={styles.UpVote}>{data.upvotes}</Text>
</View>
<View style={styles.verticalLine}></View>
<View style={styles.Postrow1}>
<Text style={styles.followerTxt}>DownVotes</Text>
<Text style={styles.UpVote}>{data.downvotes}</Text>
</View>
<View style={styles.verticalLine}></View>
<View style={styles.Postrow1}>
<Text style={styles.followerTxt}>Posts</Text>
<Text style={styles.UpVote}>{data.post.length}</Text>
</View>
</View>
<Text style={styles.decs}>Hello this is des</Text>
</View>
<View style={styles.section1}>
<Text style={styles.postTxt}>Your Posts</Text>
<View style={styles.posts}>
{
data.post.map((item) => {
return (
<Image key={item.id} style={styles.Postimage} source={{ uri: item.postimg }} />
)
})
}
</View>
</View>
)
the in your screen call the flatlist:
<FlatList
data={/*here pass your data*/}
keyExtractor={(item, index) => index.toString()} // use index better than using item.id
renderItem={renderItem}
nestedScrollEnabled={true}
/>
You can Use Below Code :-
const renderItem=({item,index})=>{
return(
<View style={styles.section1}>
<Image style={styles.profileimg} source={{
uri:item.profilepic}} />
<Text style={styles.usernameText}>#{item.username}</Text>
<View style={styles.Postrow}>
<View style={styles.Postrow1}>
<Text style={styles.followerTxt}>UpVotes</Text>
<Text style={styles.UpVote}>{item.upvotes}</Text>
</View>
<View style={styles.verticalLine}></View>
<View style={styles.Postrow1}>
<Text style={styles.followerTxt}>DownVotes</Text>
<Text style={styles.UpVote}>{item.downvotes}</Text>
</View>
<View style={styles.verticalLine}></View>
<View style={styles.Postrow1}>
<Text style={styles.followerTxt}>Posts</Text>
<Text style={styles.UpVote}>{item.post.length}</Text>
</View>
</View>
<Text style={styles.decs}>Hello this is des</Text>
</View>
<View style={styles.section1}>
<Text style={styles.postTxt}>Your Posts</Text>
<View style={styles.posts}>
{
item.post.map((item) => {
return (
<Image key={item.id} style={styles.Postimage} source={{ uri: item.postimg }} />
)
})
}
</View>
</View>
)
}
<FlatList
data={your_data}
keyExtractor={item=>item.id}
renderItem={renderItem}
/>
I am using flatlist for show user input notes in my app. But Flat List is not render any item that i entered. I used static list for testing and it works correctly. but when i enter a text through textinput it is not showing.
const addToDoHandler = () => {
if(userInput == ''){
return;
}
const newTodo = {
id: Math.floor(Math.random() * 1000),
text: userInput,
completed: false,
};
const newTodos = [...todos, newTodo];
setTodos(newTodos);
//clear user input
setUserInput('');
};
const renderItem = ( {item} ) => {
<View style={{backgroundColor:'#6b4d87', marginVertical: 10, flexDirection:'row', alignItems:'center', justifyContent:'space-between', height:60, width:'95%', borderRadius:10 }}>
<View>
<Text style={{color:'black', fontSize:20, fontWeight:'bold'}}>{item.text}</Text>
</View>
<TouchableOpacity onPress={() => deleteHandler(item.id)}>
<TrashIcon size={35} name="trash" style={{color:'#eff9f0'}} />
</TouchableOpacity>
</View>
};
return (
<SafeAreaView style={styles.root}>
<View style={styles.txtInputView}>
<TextInput
value={userInput}
onChangeText={text => setUserInput(text)}
style={styles.textInput}
placeholder={"Enter Your Note..."}
/>
<TouchableOpacity style={styles.addButton} onPress={addToDoHandler}>
<PlusSign size={35} name="add-sharp" style={styles.plusIcon}/>
</TouchableOpacity>
</View>
<View style={{alignItems:'center'}}>
<FlatList
data={todos}
renderItem={renderItem}
keyExtractor={item => item.id}
/>
</View>
</SafeAreaView>
);
You need to return the components from renderItem.
Change it to:
const renderItem = ( {item} ) => (
<View style={{backgroundColor:'#6b4d87', marginVertical: 10, flexDirection:'row', alignItems:'center', justifyContent:'space-between', height:60, width:'95%', borderRadius:10 }}>
<View>
<Text style={{color:'black', fontSize:20, fontWeight:'bold'}}>{item.text}</Text>
</View>
<TouchableOpacity onPress={() => deleteHandler(item.id)}>
<TrashIcon size={35} name="trash" style={{color:'#eff9f0'}} />
</TouchableOpacity>
</View>
);
i have data from firebase and i want map it to my custom panels but it seems not mapped (my panels do not show up) but when i console log it, the data succesfully retreived. here is my code
constructor(props) {
super(props);
this.state ={
requests:[]
}
}
componentDidMount(){
this.fetchRequests();
}
fetchRequests(){
this.subscriber = firebase.firestore()
.collection("requests").onSnapshot(docs => {
let requests = []
docs.forEach(doc => {
requests.push(doc.data())
})
this.setState({requests})
})
}
buildPanels() {
this.state.requests.map((req, idx) => {
return <View key={idx} style={styles.panel}>
<View style={{flex: 1}}>
<View style={styles.panelRow}>
<Text style={styles.panelText}>Nama Resipien</Text>
<Text style={styles.panelText}>{req.name}</Text>
</View>
<View style={styles.panelRow}>
<Text style={styles.panelText}>Golongan Darah</Text>
<Text style={{flex: 0.5}}>{req.golDarah}</Text>
</View>
</View>
</View>
})
render(){
return(
<View style={styles.container}>
<ScrollView>
{this.buildPanels()}
</ScrollView>
</View>
);
}
Add return method in your code like
buildPanels() {
return this.state.requests.map((req, idx) => {
return <View key={idx} style={styles.panel}>
<View style={{flex: 1}}>
<View style={styles.panelRow}>
<Text style={styles.panelText}>Nama Resipien</Text>
<Text style={styles.panelText}>{req.name}</Text>
</View>
<View style={styles.panelRow}>
<Text style={styles.panelText}>Golongan Darah</Text>
<Text style={{flex: 0.5}}>{req.golDarah}</Text>
</View>
</View>
</View>
})
I have a list of cards,
when pressed to any of them, I want to Increase hight for that card,
So I use layoutAnimation to handle this case because when I use Animated API from RN, I got an error when setNativeDrive "height"
Anyway,
In my case, it increases height for every card in the list,
So how can I solve it?
Code snippet
Live Demo
const OpenedAppointments = ({slideWidth}) => {
const [currentIndex, setCurrentIndex] = React.useState(null);
const [cardHeight, setCardHeight] = useState(140);
const collapseCard = (cardIndex) => {
setCurrentIndex(cardIndex);
currentIndex === cardIndex
? (LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut),
Animated.spring(),
setCardHeight(200))
: (LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut),
Animated.spring(),
setCardHeight(140));
};
const renderItems = (item, index) => {
return (
<TouchableOpacity
delayPressIn={0}
onPress={() => collapseCard(index)}
key={item.id}>
<Animated.View
style={[
styles.itemContainer,
{
height: cardHeight,
},
]}>
<View style={styles.headerContainer}>
<View style={styles.imgContainer}>
<Image
resizeMode="cover"
style={styles.img}
source={{uri: item.vendorInfo.vendorImg}}
/>
</View>
<View style={{width: '80%'}}>
<View style={styles.titleContainer}>
<Text numberOfLines={1} style={styles.vendorName}>
{item.vendorInfo.name}
</Text>
<View style={{flexDirection: 'row', alignItems: 'center'}}>
<Text style={styles.rateText}>{item.vendorInfo.rate}</Text>
<AntDesign name="star" size={18} color="#262626" />
</View>
</View>
<View style={styles.socialContainer}>
<View
style={{
width: 32,
height: 32,
backgroundColor: '#000',
borderRadius: 5,
}}
/>
</View>
</View>
</View>
<View style={styles.footer}>
<Text style={styles.serviceName}>
{item.serviceName}
</Text>
<Text style={styles.price}>
{item.price}
</Text>
</View>
// this will appeared when pressed to card "Footer Card"
<View>
<View style={styles.line} />
<View style={styles.editFooter}>
<View style={styles.dateContainer}>
<MemoCalender
style={styles.calenderIcon}
size={26}
color="#000"
/>
<View style={styles.dateBox}>
<Text style={styles.dateText}>{item.date}</Text>
<Text style={styles.dateText}>{item.time}</Text>
</View>
</View>
</View>
</View>
</Animated.View>
</TouchableOpacity>
);
};
return(
<>
{Data.opened.map((item, index) => renderItems(item, index))}
</>
);
}
Change this:
<Animated.View
style={[
styles.itemContainer,
{
height: cardHeight,
},
]
>
{...}
</Animated.View>
by
<Animated.View
style={[
styles.itemContainer,
{
height: currentIndex === index ? cardHeight : 140,
},
]
>
{...}
</Animated.View>
If you want to be more efficient, the default height of your card, define it in a constant (ex: const = DEFAULT_CARD_HEIGHT = 140) and use this constant wherever you use 140 as card height
I am working on a react native application. I have to show multiple images. My code is:
render() {
if (!this.props.data) {
return(<Text style={styles.noIMG}>Keine Bilder vorhanden</Text>)
}
return (
<View>
<View style={styles.view}>
{
(
this.props.data == '' ||
this.props.data == null ||
this.props.data == undefined
) ? null :
this.props.data.map(img => {
console.log(img.image);
console.log("Image displayed");
return(
<TouchableHighlight
key={this.uuidv4()}
onPress={()=>{
this.setState({zoom: img.image})
}}
>
<Image
style={styles.imagePreview}
source={{uri: img.image}}
/>
</TouchableHighlight>)
})
}
</View>
{ this.state.zoom ?
<Card>
<PinchZoomView scalable={false}>
<FitImage resizeMode="contain" source={{uri: this.state.zoom}}/>
</PinchZoomView>
<TouchableOpacity
style={styles.btn}
onPress={() => this.deleteImage(this.state.zoom)}>
<Text style={{color:'white'}}>Delete Image</Text>
</TouchableOpacity>
</Card> :
<View style={styles.container}><Text>Bild zum vergrößern antippen.</Text></View>
}
</View>
);
}
I do get two images in "props.data" but on screen only one image is displayed. The css code is:
const styles = StyleSheet.create({
imagePreview:{
width: 100,
height: 100,
margin: 5
}
});
render() {
return (
<View style={{ flex: 1, flexDirection:'row'}}>
{data.map((value, i) => {
return (
<View key={i}>
<TouchableOpacity>
<Image
source={{ uri: value.imageUrl }}
style={{ width: 50, height: 50 }}
resizeMode={"stretch"}
/>
</View>
</TouchableOpacity>
);
})}
</View>
);
}
Try using a FlatList
<FlatList
data={this.props.data}
extraData={this.state}
renderItem={({ item }) => {
return (
<View>
<TouchableOpacity onPress={() => this.setState({zoom: img.image})}>
<Image
source={{ uri: item.image }}
PlaceholderContent={<ActivityIndicator />}
/>
</TouchableOpacity>
</View>
)
}}
keyExtractor={(item, index) => index.toString()}
/>