I try to show some items inside a ScrollView, but it shows me this error.
VirtualizedLists should never be nested inside plain ScrollViews with
the same orientation - use another VirtualizedList-backed container
instead.
I tried with scrollview, but i need columns in my list.
return (
<View>
<ScrollView style={{backgroundColor: '#612d7c'}} >
<View style={{marginTop: headerHeight}}>
<ProfilePictureItem />
</View>
<View style={styles.badgeTextContainer}>
<Text style={styles.badgeText}>Badges</Text>
</View>
<Card style={styles.card}>
<FlatList
data={products}
style={{marginBottom: 20}}
renderItem={itemData => (
<BadgeItem key={itemData.item.id} style={styles.badge}/>
)}
numColumns={3}
/>
</Card>
</ScrollView>
</View>
);
That's right, either you display a ScrollView or a FlatList if you use the same scroll direction. For example, you can use the FlatList with the ListHeaderComponent prop.
You can try this:
function renderListHeader() {
return (
<View style={{marginTop: headerHeight}}>
<ProfilePictureItem />
</View>
<View style={styles.badgeTextContainer}>
<Text style={styles.badgeText}>Badges</Text>
</View>
)
}
.....
return (
<FlatList
data={products}
ListHeaderComponent={renderListHeader()}
style={{marginBottom: 20}}
renderItem={itemData => (
<BadgeItem key={itemData.item.id} style={styles.badge}/>
)}
numColumns={3}
/>
);
I am developing a project with react native. I have a header with a Text and an Icon.
const Header = ({ navigation, state }) => (
<View style={styles.header}>
<View style={styles.identidadeAppContainer}>
<View style={styles.nomeAppContainer}><Text style={styles.nomeAppText}>BigodeAPP</Text></View>
<View style={styles.logoAppContainer}><Image style={styles.imageLogo} source={Images.logoBigodeApp}></Image></View>
</View>
<View style={styles.iconContainer}>
{
!state ?
<Icon name="angle-down" size={25} color={colors.secundary} />
:
<Icon name="cut" size={25} color={colors.secundary} />
}
</View>
</View>
)
I call the Header inside my APP:
<Header state={stateMenu} />
stateMenu is a boolean variable which changes according to the user's actions.
However, even with stateMenu changing value, I am not able to re-embed the header to make the Icon later.
How can I do it?
I think, you can do by using this way:
const Header = ({ navigation, state }) => (
<View style={styles.header}>
<View style={styles.identidadeAppContainer}>
<View style={styles.nomeAppContainer}><Text style={styles.nomeAppText}>BigodeAPP</Text></View>
<View style={styles.logoAppContainer}><Image style={styles.imageLogo} source={Images.logoBigodeApp}></Image></View>
</View>
<View style={styles.iconContainer}>
<Icon name={state ? "cut" : "angle-down"} size={25} color={colors.secundary} />
</View>
</View>
)
Theres a one line if statement on the name prop
i'm working on a react native app and i updated my react version.
I use Flatlist inside a ScrollView.
I got this warning :
VirtualizedLists should never be nested inside plain ScrollViews with the same orientation - use another VirtualizedList-backed container instead.
My component :
return (
<KeyboardAvoidingView behavior="padding" enabled style={styles.keyboardAvoidingView}>
<SafeAreaView style={styles.keyboardAvoidingView}>
<Header
..
}}
containerStyle={styles.headerContainer}
rightComponent={{
...
}}
/>
<ScrollView style={styles.body}>
<View style={styles.titleSection}>
<Text style={styles.stepTitle}>Étape 1/3</Text>
<Text style={styles.questionTitle}>Quel contact voulez-vous partager ?</Text>
</View>
<View>
<FlatList
data={contacts}
renderItem={({ item, index }) => (
<TouchableHighlight onPress={() => this.onItemClickHandler(index, item.id, item.firstName, item.lastName)} style={styles.touchableHighlight}>
<View>
<ListItem
chevron={
(
<Icon
color={this.state.selectedIndex === index
? `${defaultTheme.palette.white.main}`
: `${defaultTheme.palette.primary.dark}`}
name="chevron-right"
size={40}
type="material"
/>
)
}
containerStyle={
this.state.selectedIndex === index
? styles.selected
: styles.notSelected
}
leftElement={
(
<Icon
...
/>
)
}
title={`${item.firstName} ${item.lastName}`}
titleStyle={this.state.selectedIndex === index
? [styles.titleStyle, styles.titleSelected]
: [styles.titleStyle, styles.defaultTitle]}
/>
</View>
</TouchableHighlight>
)}
extraData={this.state.selectedIndex}
keyExtractor={(item) => item.email}
ListHeaderComponent={this.renderHeader(searchValue)}
style={styles.flatListStyle}
ListFooterComponent={this.renderFooter}
/>
{
(contacts.length > 0 && page > 0)
&& <CustomButton title="Afficher la suite" onPress={() => this.makeRemoteRequest()} loading={loading} disabled={loading} />
}
</View>
</ScrollView>
</SafeAreaView>
</KeyboardAvoidingView>
);
I had the same issue. See my code
What I did is the component which I wanted to render outside the flatlist I included that inside the ListHeaderComponent and removed the Scrollview component. Now its working fine without any warning.
Below is the previous code:
<ScrollView >
<ReadCard data={this.state.data}/>
<FlatList
data={this.state.data.related}
keyExtractor={this._keyExtractor}
renderItem={this._renderItem}
ItemSeparatorComponent={ListSeprator}
/>
</ScrollView>
Below is the changed code without any warning:
<FlatList
data={this.state.data.related}
keyExtractor={this._keyExtractor}
renderItem={this._renderItem}
ItemSeparatorComponent={ListSeprator}
ListHeaderComponent={
<ReadCard data={this.state.data}/>
}
/>
TouchableOpacity requires us to click two times in IOS 12.2. These issues were not in previous IOS 12.1 version.
Whenever clicking on TouchableOpacity it seems to register click but do not fire onPress event. This issue is occuring in react-native version 0.52. This issue only occurs in IOS and not in android.
Code Snippet
<FlatList
scrollEnabled={false}
data={this.props.menuData[this.props.toutIndex].Menu}
keyExtractor={(data, index) => index}
renderItem={({ item , index}) => {
//alert(categoryLinks.menu_id+""+data.menu_id);
//alert(JSON.stringify(data));
return (
<TouchableOpacity onPress={()=>this.itemDetailsPage(item)} >
<View>
<CardItem onPress={()=>this.itemDetailsPage(item)} style={[styles.menuSubCategoryCardItem, {marginLeft:0, borderLeftWidth: 6, borderLeftColor: item.itemCount ? '#00CDBE' : '#FFFFFF'}]}>
<View style={{flex:2,marginLeft:"0%"}}>
<View style={styles.menuItemImageOuterContainer}>
<View style={styles.menuItemImageInnerContainer}>
<ImageLoad
style={styles.menuItemImage}
isShowActivity={false}
borderRadius={10}
source={{ uri: item.menu_photo }}
/>
{item.ratable == 'true' ?
<View style={[styles.menuItemRatingImage,{backgroundColor:item.overall_rating==0 ? 'rgb(166,166,166)' : item.rating_color}]}>
<Text style={styles.menuItemRatingImageText}>{ item.overall_rating>0 ? parseFloat(item.overall_rating).toFixed(this.state.rating_decimal_places) : "-" }</Text>
</View>
:null}
</View>
<View style={styles.menuItemNameContainer}>
<View style={{width:'100%',}}>
<Text numberOfLines={2} style={[styles.textHeadingMenuItem,{fontSize: item.menu_name.length>50 ? 53/3.82 : 63/3.82,paddingLeft:"2%"}]}>
{this.Capitalize(item.menu_name)}
</Text>
</View>
<View style={{width:'130%',}}>
<Text numberOfLines={3} note style={[styles.textMenuItem,{paddingLeft:"2%"}]}>
{item.menu_description}
</Text>
</View>
{
item.friend_review_count > 0 ?
<View style={{flexDirection:'row',marginLeft:"2%",alignItems:'center'}}>
<Image style={styles.userIconBelowMenuItemText} source={require("../../../assets/home/blueUser.png")}>
</Image>
<Text numberOfLines={1} style={styles.MenuItemFriendsRatedText}>
{item.friend_review_count} friends have rated this.
</Text>
</View>
:
null
}
</View>
</View>
</View>
<Right>
<View style={styles.menuItemPriceOuterContainer}>
<Text style={[styles.textHeadingMenuItemPrice,{paddingTop:"5%"}]}>
{this.state.currency} {CommonFunc.numberWithCommas(
parseInt(item.menu_price)
.toFixed(categoryLinks.state.decimal_places)
)
}
</Text>
</View>
<View style={styles.menuItemPlusButtonContainer}>
{ item.itemCount == undefined || item.itemCount == 0?
<TouchableOpacity style={styles.menuItemPlusButton}
onPress={() => this.displaySelector(item.menu_price, item.Menu_Options, this.props.toutIndex, null, index, 1)}
onLongPress={() => this.displaySelector(item.menu_price, item.Menu_Options, this.props.toutIndex, null, index, 1, 1)}
rejectResponderTermination
>
<Image style={[styles.menuItemPlusButtonImage,{resizeMethod:'resize'}]} source={require("../../../assets/order/Add.png")} />
</TouchableOpacity>
:
<View style={styles.menuItemSelectorContainer}>
<Button transparent onPress={() => this.displaySelector(item.menu_price, item.Menu_Options, this.props.toutIndex, null, index, -1)} style={{paddingVertical:10, paddingLeft:2}}>
<Image source={require('../../../assets/order/decrease.png')}
style={[styles.menuItemSelectorDecreaseIcon,{resizeMethod:'resize'}]}/>
</Button>
<Button transparent>
<Text style={styles.menuItemSelectorCountText}>
{item.itemCount}
</Text>
</Button>
<Button transparent onPress={() => this.displaySelector(item.menu_price, item.Menu_Options, this.props.toutIndex, null, index, 1)}
onLongPress={() => this.displaySelector(item.menu_price, item.Menu_Options, this.props.toutIndex, null, index, 1, 1)}
style={{paddingVertical:10, paddingRight:2}}
>
<Image source={require('../../../assets/order/increase.png')}
style={[styles.menuItemSelectorDecreaseIcon,{resizeMethod:'resize'}]}/>
</Button>
</View>
}
</View>
</Right>
</CardItem>
</View>
</TouchableOpacity>
);
}}
/>
</View>
</View>
}
use
keyboardShouldPersistTaps='always'
on parent components to the TouchableOpacity inorder for child touchables to persist the taps.
for eg1
<Flatlist keyboardShouldPersistTaps='always'>
<TouchableOpacity/>
</Flatlist>
eg2:
<TouchableOpacity keyboardShouldPersistTaps='always'>
<TouchableOpacity></TouchableOpacity>
</TouchableOpacity>
This, most probably, is a conflict between react components. While updating to latest react might do the trick, but I would advice you to try and remove each and every component and see if it works.
Are you using PanResponder by any chance? This could also create a conflict. Thanks and good luck.
Try react-native 0.55.4 its a stable version and i mostely use in my personal projects.
and try to wrap your image inside a View like this\
<TouchableOpacity>
<View>
<Image />
</View>
</TouchableOpacity>
You have 2 onPress nested functions, in <TouchableOpacity> and <Card>, which both are calling the same item, delete onPress function of <Card> component and it will mostly work
I know there are already so many queries on this topic, I have tried every step but still won't be able to fix the issue.
Here is the code :
render() {
const {sContainer, sSearchBar} = styles;
if (this.props.InviteState.objectForDeleteList){
this.updateList(this.props.InviteState.objectForDeleteList);
}
return (
<View style={styles.mainContainer}>
<CustomNavBar
onBackPress={() => this.props.navigation.goBack()}
/>
<View
style={sContainer}
>
<ScrollView keyboardShouldPersistTaps="always">
<TextInput
underlineColorAndroid={'transparent'}
placeholder={'Search'}
placeholderTextColor={'white'}
selectionColor={Color.colorPrimaryDark}
style={sSearchBar}
onChangeText={(searchTerm) => this.setState({searchTerm})}
/>
</ScrollView>
{this.renderInviteUserList()}
</View>
</View>
);
}
renderInviteUserList() {
if (this.props.InviteState.inviteUsers.length > 0) {
return (
<SearchableFlatlist
searchProperty={'fullName'}
searchTerm={this.state.searchTerm}
data={this.props.InviteState.inviteUsers}
containerStyle={styles.listStyle}
renderItem={({item}) => this.renderItem(item)}
keyExtractor={(item) => item.id}
/>
);
}
return (
<View style={styles.emptyListContainer}>
<Text style={styles.noUserFoundText}>
{this.props.InviteState.noInviteUserFound}
</Text>
</View>
);
}
renderItem(item) {
return (
this.state.userData && this.state.userData.id !== item.id
?
<TouchableOpacity
style={styles.itemContainer}
onPress={() => this.onSelectUser(item)}>
<View style={styles.itemSubContainer}>
<Avatar
medium
rounded
source={
item.imageUrl === ''
? require('../../assets/user_image.png')
: {uri: item.imageUrl}
}
onPress={() => console.log('Works!')}
activeOpacity={0.7}
/>
<View style={styles.userNameContainer}>
<Text style={styles.userNameText} numberOfLines={1}>
{item.fullName}
</Text>
</View>
<CustomButton
style={{
flexWrap: 'wrap',
alignSelf: 'flex-end',
marginTop: 10,
marginBottom: 10,
width: 90,
}}
showIcon={false}
btnText={'Add'}
onPress={() => this.onClickSendInvitation(item)}
/>
</View>
</TouchableOpacity> : null
);
}
**I even tried with bellow code as suggested by #Nirmalsinh **:
<ScrollView keyboardShouldPersistTaps="always" style={sContainer}>
<CustomNavBar
onBackPress={() => this.props.navigation.goBack()}
/>
<TextInput underlineColorAndroid={'transparent'}
placeholder={'Search'}
placeholderTextColor={'white'}
selectionColor={Color.colorPrimaryDark}
style={sSearchBar}
onChangeText={(searchTerm) => this.setState({searchTerm})} />
{this.renderInviteUserList()}
</ScrollView>
I have followed this article:
https://medium.com/react-native-training/todays-react-native-tip-keyboard-issues-in-scrollview-8cfbeb92995b
I have tried with keyboardShouldPersistTaps=handled also but still, I have to tap twice on my Custom Button to perform an action. Can anybody tell me what I am doing wrong inside the code?
Thanks.
You need to add give value always in keyboardShouldPersistTaps to allow user tap without closing the keyboard.
keyboardShouldPersistTaps='always'
For example:
<ScrollView keyboardShouldPersistTaps='always'>
// Put your component
</ScrollView>
NOTE: Kindly put your tappable component inside the ScrollView. Otherwise it won't work.
You can use keyboardShouldPersistTaps='handled' in a ScrollView or Scrollables like FlatList SectionList etc. and embed a TouchableWithoutFeedBack to handle the case for dismiss on outside clicks.
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
<ScrollView keyboardShouldPersistTaps='handled'>
// Rest of the content.
</ScrollView/>
</TouchableWithoutFeedback>
For FlatList and SectionList you will have to handle KeyBoard.dismiss separately.
Please try this, It's working for me, it will works you also, i hope it helps...