React-Native : calculating the scrollToItem of a FlatList with a ref on componentDidMount and rendering it - react-native

I have a FlatList which renders numbers from 1-10 along with a radio button. If I have pre-selected number which could be dynamic, that numbered radio button is pre-selected. How to calculate the scrollToItem/scrollToIndex in this case ?
componentDidMount() {
this.scrollToItem();
}
scrollToItem = () => {
let dynamicIndex = dynamicIndex
//calcuate the dynamic Index
this.flatListRef.scrollToIndex({ animated: true, index: dynamicIndex });
};
<FlatList
ref={ref => {this.flatListRef = ref;}}
bounces={false}
keyExtractor={item => item.id}
data={listData}
renderItem={({ item, index })=>
this.renderItem(item,index)}
/>
But it throws error "Cannot read property 'scrollToIndex' of index. Basically it can't find 'this.flatListRef' during component mount.

Related

scrolltolocation not working outside of initialNumToRender props window in Sectionlist untill I manually scroll

I am using sectionlist for showing data in react native.
I have large data with a section list.
Here We use scrolltolocation for scrolling to the specific section but it is not working until I render to that section using manual scroll
My Code:
<SectionList
sections={this.props.fooddata}
ref={(s) => (this.sectionList = s)}
//onScroll={this.handleScroll}
stickySectionHeadersEnabled={true}
onViewableItemsChanged={this.props.onCheckViewableItems}
viewabilityConfig={{
itemVisiblePercentThreshold: 50 //means if 50% of the item is visible
}}
removeClippedSubviews={false}
maxToRenderPerBatch={6}
scrollEnabled={true}
onScrollToIndexFailed={info => {
const wait = new Promise(resolve => setTimeout(resolve, 500));
wait.then(() => {
//flatList.current?.scrollToIndex({ index: info.index, animated: false });
});
}}
initialNumToRender={4}
windowSize={5}
ListFooterComponent={this.ItemSeprator}
style={{ width: this.windowwidth,top:this.props.searchclicked?135:(this.props.nonveg || this.props.veg)?200:117,bottom:0,position:'absolute'}}
// keyExtractor={(item, index) => index}
keyExtractor={this.keyExtractor}
renderSectionHeader={({ section,index }) => this.createSection(section,index)}
// renderItem={(item)=>this.jackRecommned(item)} //{({ item, index }) => this.renderItem(item, index)}
renderItem={this.renderItem.bind(this)}
renderFooter={this.footer}
/>

CheckBox in FlatList

I would like to present the user with a list of items to choose from. The items are sourced from a Redux state object. It is a list of the contacts on the device.
I used a "FlatList" from React-Native and a "ListItem" from React-Native-Elements. The ListItem has a CheckBox.
For the user to check/uncheck an item in the list, he/she can click on the CheckBox or any part of the ListItem.
My 1st Attempt: As you can see in the following code, I had to duplicate part of the code to achieve this. Is there a smarter way of doing this (to avoid code duplication)?
<FlatList
keyExtractor={(item, index) => index.toString()}
data={props.contactList}
renderItem={_renderItem}
ListEmptyComponent={<Text>There are no contacts to show.</Text>}
refreshing={state.refreshing}
onRefresh={_onRefresh}
/>
const _renderItem = ({ item, index }) => {
return (
<ListItem
title={item.name}
onPress={() => {
// The following 2 statements are repeated (below)!!!
_toggleCheck(index);
props.acContactSelect(index);
}}
checkBox={{
checked: _isItemChecked(index),
checkedIcon: "check",
onPress: () => {
// The following 2 statements are repeated (above)!!!
_toggleCheck(index);
props.acContactSelect(index);
},
}}
/>
);
};
My 2nd Attempt: I tried using a function. I got the error message (Maximum update depth exceeded.)
<FlatList
.. {similar to the code above}
/>
const _renderItem = ({ item, index }) => {
return (
<ListItem
..
onPress={_onPress(index)}
checkBox={{
..
onPress: _onPress(index),
}}
/>
);
};
const _onPress = (index) => {
_toggleCheck(index);
props.acContactSelect(index);
};
Thanks for your effort and time to help...
Please change this code
<ListItem
..
onPress={_onPress(index)}
checkBox={{
..
onPress: _onPress(index),
}}
/>
to
<ListItem
..
onPress={() =>_onPress(index)}
checkBox={{
..
onPress:() => _onPress(index),
}}
/>
onPress={_onPress(index)} will call function immediately

numColumns breaks scrollToIndex react native FlatList

I'm using react native's FlatList to display a list of items, and also check which items are currently viewable. In my items there's one item which is marked mostUsed if the item is not viewable I display a link at the top, the user can click that and scroll to that item, using scrollToIndex. scrollToIndex works well without setting numColumns, when I set numColumns={2} I get scrollToIndex out of range: 9 vs 4 error.
setScrollIndex = () => {
if (this.state.scrollIndex !== 0) {
return;
}
for (let i = 0; i < this.state.items.length; i++) {
const items = this.state.items;
if (items[i] && items[i].mostUsed) {
this.setState({
scrollIndex: i,
});
}
}
};
// scroll to index function
scrollToIndex = () => {
this.flatListRef.scrollToIndex({
animated: true,
index: this.state.scrollIndex,
});
};
<FlatList
data={this.state.items}
numColumns={2}
keyExtractor={(item, index) => index.toString()}
ref={ref => {
this.flatListRef = ref;
}}
showsVerticalScrollIndicator={false}
onViewableItemsChanged={this.handleViewableItemsChanged}
viewabilityConfig={this.viewabilityConfig}
renderItem={({ item, index }) => (
<Card
title={item.title}
description={item.description}
mostUsed={item.mostUsed}
style={{ width: item.width }}
/>
)}
/>
expo snack
Looks like FlatList's scrollToIndex changes the way it views index if numColumns is higher then 1.
It may be more correct to call it scrollToRowIndex since it does not work on item index in case of multiple columns.
For your case this worked for me on expo:
scrollToIndex = () => {
this.flatListRef.scrollToIndex({
animated: true,
index: Math.floor(this.state.scrollIndex / numColumns),
});
};

how to make flatlist component of react-native scroll to bottom when its first rendered?

I am trying to build a Chat Application using react-native and using flatlist to display the messages. And i want my list to stay at bottom always can anyone plzz suggest me a solution.
Basically you need to use scrollToEnd on flatList..
First: create a flatList reference with:
ref={ (ref) => { this.myFlatListRef = ref } }
Second: add onContentSizeChange listener on flatList
onContentSizeChange={ () => { this.myFlatListRef.scrollToEnd({animated:true}) } }
Third: add onLayout listener on flatList for scroll to bottom when keyboard is showed.
onLayout={ () => { this.myFlatListRef.scrollToEnd({animated:true}) } }
eg:
<FlatList
ref={ (ref) => { this.myFlatListRef = ref } }
onContentSizeChange={ () => { this.myFlatListRef.scrollToEnd({animated:true}) } }
onLayout={ () => { this.myFlatListRef.scrollToEnd({animated:true}) } }
data={this.state.messages}
renderItem={ ({item}) => <Item data={item} /> }
/>
the simplest way to do this is to use inverted props in the flatlist
this allow us to render list up-side-down
for more ref. vidit https://facebook.github.io/react-native/docs/flatlist#inverted
Here, you can do this -
const messageData = this.props.convo
return (
<View style={{ flex: 1 }}>
<FlatList
inverted={-1}
style={styles.list}
extraData={this.props}
data={messageData}
keyExtractor = {(item) => {
return item.id;
}}
renderItem=
{this.renderItem}
/>
after that, you will get an inverted list which will have the topmost elements in the list, so for fixing this you can add reverse() in your flatlist data or in your reducer. Like this-
data={messageData.reverse()} or in reducer return { ...state, chats: action.payload.reverse() }
You can give a refto FlatList and access certain flatList properties that can scroll at particular position. Here below resolution should work.
setTimeout(() => this.refs.flatList.scrollToEnd(), 200)
ScrollToEnd React native

React-Native re-render Flatlist

I'm having trouble keeping the data in my Flatlist after coming back from another page. My scenario is as follows:
User goes to homepage and scrolls through 20 items
User clicks their profile tab changing page using react-native-router-flux
User clicks the home tab taking them back to the list however the list re-renders and starts from the top.
How can I stop this re-rendering and fetching the same data again?
componentDidMount() {
this.makeRemoteRequest();
}
makeRemoteReuest gets my data from firebase in batches of 5 and sets data: []
data: [...this.state.data, ...results]
I've tried using the below but not sure if this is correct, when i navigate away and back the data re-renders. I want to keep the data so the page will be exactly the same as when it was left.
shouldComponentUpdate(nextProps, nextState) {
if (JSON.stringify(this.state.data) !== JSON.stringify(nextState.data)) {
return true;
}
return false;
}
My flatlist:
<View>
<FlatList
scrollsToTop={false}
ref={(ref) => { this.flatListRef = ref; }}
showsHorizontalScrollIndicator={false}
onScroll={this.handleScroll}
data={this.state.data}
keyExtractor={item => item.key}
ListFooterComponent={this.renderFooter()}
onRefresh={this.handleRefresh}
refreshing={this.state.newRefresh}
onEndReached={this.handleEndRefresh}
onEndReachedThreshold={0.05}
getItemLayout={this.getItemLayout}
renderItem={this.renderItem}
/>
{this.state.refreshAvailable ? this.renderRefreshButton() : null}
</View>
Thanks for any help!
Coded long back for the dumb project, maybe this can help you
The View: used onLayout Prop for getting the y-axis
<ScrollView
ref={(ref) => this.scrollTo = ref}
contentContainerStyle={{margin:5,}}
>
<Card onLayout={(event) => this._findHeight(event.nativeEvent.layout, 'personal')}>
<Personal review={true}/>
</Card>
</ScrollView>
The Function: stored the y-axis; here i have used realm db
_findHeight = (e, name) => {
const {x, y, width, height} = e;
this.realm.write(() => {
this.realm.create('yLocation',{names:name,yaxis:y}) :
});
}
The AutoScroll Method: here i have used scrollTo method from ScrollView you can use any method using their ref
_scrollTo = (y) => {
this.scrollTo.scrollTo({x:0,y:y,animated:true});
}
Note : Call _scrollTo method in componentDidMount