I am new to react native. I am facing problem in maintaining the position of flatlist when navigating forward and then come back to that screen.
Current behavior
Try handling scroll position changing on a state:
<FlatList onScroll={this.handleScroll} />
handleScroll method:
handleScroll: function(event: Object) {
this.setState({ scrollPosition: event.nativeEvent.contentOffset.y });
}
Then you can use scrollToOffset(this.state.scrollPosition) when you navigate back.
If you use react-navigation and want to keep the scroll position after navigation, try this hack:
componentDidMount() {
this.props.navigation.addListener('willBlur', () => {
const offset = this.state.scrollPosition
// To prevent FlatList scrolls to top automatically,
// we have to delay scroll to the original position
setTimeout(() => {
this.flatList.scrollToOffset({ offset, animated: false })
}, 500)
})
}
I'm using react-navigation to navigate between a FlatList and a details view. I'm also using react-redux to track state. Here's the process I've followed.
That's all a little easier said then done and in my own Component the rows in my FlatList are variable so that complicates calculating the offset but heres an example assuming your rows are the same
My App component which renders the navigator
handleNavigationStateChange = (prevState, newState) => {
this._getCurrentRouteName(newState)
}
_getCurrentRouteName = (navState) => {
if (navState.hasOwnProperty('index')) {
this._getCurrentRouteName(navState.routes[navState.index])
} else {
// This is my redux action to save route name
this.props.updateCurrentRoute( navState.routeName )
}
}
<AppNavigator onNavigationStateChange={this.handleNavigationStateChange} />
My component with the FlatList looks like this
// Renders a row for the FlatList with TouchableHighlight to call viewCreation
renderItem = ( row ) => {
let creation = row.item
return (
<CreationCard onPress={this.viewCreation} index={row.index} creation={creation} />
)
}
viewCreation = ( index ) => {
// Get the creation
let currentCreation = this.props.creations[index]
// Another reducer saves both my item and index that was selected
this.props.setSelectedIndex(currentCreation, index)
// Navigate to the details screen
this.props.navigation.navigate('CreationDetailScreen')
}
// Assuming all rows are 50 height
getItemLayout = (data, index) => {
return {length: 50, offset: 50 * index, index}
}
// We mapped the 'currentRoute' property to this component so check
// the props when the component receives new ones.
componentWillReceiveProps( nextProps ){
// If the currentRoute matches the route for this screen
if( nextProps.currentRoute === 'CreationListScreen' ){
// If we also know the last index that was selected on this page
if( this.props.lastCreationIndex ){
// Calculate the offset for the last index selected
let y = this.props.lastCreationIndex * 50
// and finally scroll to the offset
this._flatList.scrollToOffset({
offset: y,
animated: true
})
}
}
}
// IMPORTANT to include getItemLayout
render(){
return(
<FlatList
ref={(fl) => this._flatList = fl}
data={this.props.creations}
renderItem={this.renderItem}
getItemLayout={this.getItemLayout}
keyExtractor={creation => creation.id}
/>
)
}
In Flatlist set scrollsToTop={false}
this will retain position when you navigate back from detail screen. I am using Expo version 25.