I have been working my way through legacy views within an app - resolving the issues of FlatLists within a ScrollView component casuing the resulting Virtualised Lists error that is displayed.
I have 5 affected pages - first 3 only had 1 flatlist in the view - so was easy enough to split the urrounding code into flatlist header and footer assets. However I'm not sure what to do in terms of having 2 or more flatlists - how do i apprach the layout in thsi scenario - so there is only 1 scroll?
I may be missing something very simple but need a nudge please!
here is the view code:
<View style={[PRStyles.IRContainer]} >
<StatusBar barStyle="light-content" />
<View style={PRStyles.header}>
<FixedHeader backButton={true} navScreen='HomeViewContainer' />
</View>
<View style={PRStyles.IRBody}>
<ScrollView
refreshControl={
<RefreshControl
refreshing={this.state.refreshing}
onRefresh={this._onRefresh} />}>
<KeyboardAvoidingView>
<TitleHeader sectionLocaleTxt='Duty Record' sectionTxt='' sectionDesc='End of shift duty Record.' sectionHyphen={false} />
<View style={FormStyles.PrRow}>
<Text style={FormStyles.PrRowTitle}>{this.props.auth.checkedInVenueName}</Text>
<Text style={FormStyles.PrRowDate}>{this.getCurrentDate()}</Text>
</View>
<View style={FormStyles.PrRow}>
<Text style={FormStyles.PrRowSubTitle}>General Manager / Licence Holder:</Text>
<View style={FormStyles.PrTable}>
<View style={FormStyles.prRowStrip}><Text style={FormStyles.prRowStripText} >{this.state.licenceHolder}</Text></View>
</View>
</View>
<View style={FormStyles.PrRow}>
<Text style={FormStyles.PrRowSubTitle}>Door Staff (<Text style={FormStyles.PrRowCount}>{this.state.doorStaffCount}</Text> total)</Text>
<View style={FormStyles.PrTable}>
<FlatList
scrollEnabled={true}
data={this.state.rotaRecords}
keyExtractor={(item, index) => index.toString()}
ListEmptyComponent={this._listStaffEmptyComponent}
renderItem={this._renderDoorStaffItem}
/>
</View>
</View>
<View style={FormStyles.PrRow}>
<Text style={FormStyles.PrRowSubTitle}>Numbers:</Text>
<View style={FormStyles.PrTable}>
<View style={FormStyles.prRowStrip}><Text style={FormStyles.prRowStripText} >Total In <Text style={ FormStyles.prRowStripColon}>:</Text> <Text style={FormStyles.prRowStripOrText}>{this.state.totalIn}</Text></Text></View>
<View style={FormStyles.prRowStrip}><Text style={FormStyles.prRowStripText} >Total Out<Text style={FormStyles.prRowStripColon}>:</Text> <Text style={FormStyles.prRowStripOrText}>{this.state.totalOut}</Text></Text></View>
<View style={FormStyles.prRowStrip}><Text style={FormStyles.prRowStripText} >Overall Difference<Text style={FormStyles.prRowStripColon}>:</Text> <Text style={FormStyles.prRowStripOrText}>{this.state.totalDifference}</Text></Text></View>
</View>
</View>
<View style={FormStyles.PrRow}>
<Text style={FormStyles.PrRowSubTitle}>Door Counts:</Text>
<FlatList
scrollEnabled={true}
data={this.state.countRecords}
keyExtractor={(item, index) => index.toString()}
ListEmptyComponent={this._listDoorCountEmptyComponent}
ListHeaderComponent={this._listDoorCountHeaderComponent}
renderItem={this._renderDoorCountItem}
/>
</View>
<View style={[FormStyles.form, FormStyles.PrRow, {marginTop:15, paddingTop:0, borderBottomWidth:0} ]}>
<Text style={ModalStyles.formTop}><Text style={[ModalStyles.required, ]}>*</Text>Required Field</Text>
<Text style={[FormStyles.formLabel, FormStyles.formlabelFirst ]}>1. Customer Comments:</Text>
<View style={FormStyles.textInputBlock}>
<TextInput
placeholder="Enter Comments"
numberOfLines={4}
onChangeText={val => this.setState({ comments: val})}
value={this.state.comments}
multiline
style={{minHeight: 280, height: 'auto', textAlignVertical: 'top'}}
/>
</View>
<Text style={[FormStyles.formLabel, FormStyles.formlabelFirst ]}>2. Duty Manager Name<Text style={ModalStyles.required}>*</Text> :</Text>
<View style={FormStyles.textInputBlock}>
<TextInput
ref='signatureName'
placeholder="Please Print Name"
style={FormStyles.textInputText}
autoCorrect={false}
returnKeyType='done'
value={this.state.signatureName}
onChangeText={(text) => this.setState({signatureName:text})}
/>
</View>
<Text style={[FormStyles.formLabel, FormStyles.formlabelFirst ]}>3. Duty Manager Signature: <Text style={ModalStyles.required}>*</Text></Text>
<Text style={[FormStyles.formLabelSub, FormStyles.formLabelSubHigh, FormStyles.superHighLight ]}>Note: PRESS BLUE SAVE BUTTON after applying Signature</Text>
<View style={[FormStyles.textInputBlock, this.isSignatureAdded() && FormStyles.signatureBlock ]}>
{this.signatureBlock()}
</View>
</View>
{submitButton}
</KeyboardAvoidingView>
</ScrollView>
</View>
</View>
This is the most common error when working with scroll view and flat list.
To prevent the error cause, we have to manage our views inside a single flat list and put other components in the list header component and list footer component in an efficient way as we desire.
<FlatList
data={this.state.countRecords}
renderItem={(item) => {
return (
// Your flat list item goes here..
)
}}
ListHeaderComponent={
// Content above the list goes here..
}
ListFooterComponent={
// Content below the list should goes here..
}
/>
You can still check the below link for more understanding.
FlatList Example with Custom Header and Custom Footer
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 make check box list on Model Pop up by using react native multiple select checkbox list listed but it take full screen height i am not able to fix this issue please Any body help me
below is my Model Pop up Code
[![<Modal
animationType="slide"
transparent={true}
visible={this.state.modalVisible}
onRequestClose={() => {
Alert.alert("Modal has been closed.");
}}
>
<View style={styles.ModalcenteredView}>
<View style={styles.ModalView}>
<View style={{height:'30%'}}>
<SelectMultiple
items={this.state.ParticipantCheckBox}
// renderLabel={renderLabel}
selectedItems={this.state.selectedFamilyMembers}
onSelectionsChange={this.SelectFamilyMembers} />
</View>
<View style={{flex:1, flexDirection:'row', flex:1,height:'1%'}}>
<TouchableHighlight style={{height:'5%'},\[styles.ModalCloseButton\] }
onPress={() => {
this.HideShowFamilyMemberModel(false);
}}
>
<Text style={styles.ModalCloseButtonTextStyle}>Close</Text>
</TouchableHighlight>
<TouchableHighlight style={{height:'5%'},\[styles.ModalSaveButton\] }
onPress={() => {
this.SaveFamilyMemberModel(false);
}}
>
<Text style={styles.ModalSaveButtonTextStyle}>Save</Text>
</TouchableHighlight>
</View>
</View>
</View>
</Modal>][1]][1]
You can make your modal like this
<Modal>
//this is parent view
<View>
//set this vide at the center of parent view and set height 40% or 30%
<View>
<ScrollView>
…
...
</ScrollView>
</View>
</View>
</Modal>
I have a horizontal flatlist inside a vertical flatlist and I want data on the inside flatlist to be provided based on which item of the outer flatlist is being rendered
This is what I have currently:
<FlatList
style={styles.outerFlatlist}
data={this.state.catagories}
renderItem={({item, index})=>{
return (
<View>
<View>
<Text style={styles.catagoryName}>
{item.CategoryName}
</Text>
</View>
<View style={styles.innerFlatlist}>
<FlatList
horizontal={true}
data={this.state.product1}
renderItem={({item, index})=>{
return (
<View
style={styles.productsContainer}>
<View
style={styles.productImage}>
<Image
source={{uri:item.productImage}}
style={styles.image}
resizeMode='contain'>
</Image>
</View>
<View style={styles.productDETAILS}>
<Text
style={styles.productPrice}>R{item.productPrice}
</Text>
<Text
style={styles.productDescription}>
{item.productDecription}
</Text>
</View>
</View>
);
}}/>
</View>
</View>
);
}}/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
With the above code, everything works well except that each category displays the same data (this.state.product1), how can I make the data of the inner flatlist be dependant on the which item on the outer flatlist is displayed?
When you are inside the .map you already are inside the this.state.catagories , but since you always use this.state.product1 for the flatlist2 you will always get the same result because this.state.product1 stays the same.
At flatlist2 change the data to item.products or item.whateverYouNeedHereButArray
<View style={styles.innerFlatlist}>
<FlatList
horizontal={true}
data={item}
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