I'm not able to find a correct way to refresh a FlatList when bottom bar tab is pressed and that we are at the top of the FlatList.
I did succeed to reach the top of the FlatList using useScrollToTop
, also I managed to refetch data but it is not as I would like to be.
import { useScrollToTop } from '@react-navigation/native';
const flatlistRef = useRef<FlatList>(null);
useScrollToTop(flatlistRef);
This scroll to the top of the FlatList but :
I'm using React-Navigation for bottom tabs ("@react-navigation/bottom-tabs": "^6.5.16"
)
Any idea?
Thanks
Since you want to do more than just scroll to the top when the tab is focused, you should give up on using useScrollToTop
and just use useFocusEffect. The hook is called whenever the current tab comes into focus. You can both refresh the data and scroll to the top of the flatlist in this hook (demo). To refresh when home screen is pressed is add a navigation listener for tab presses and then refresh there:
import { useState, useEffect, useCallback, useRef } from 'react';
import {
View,
Text,
StyleSheet,
FlatList,
ActivityIndicator,
RefreshControl as RNRefreshControl,
Platform
} from 'react-native';
import { RefreshControl as WebRefreshControl } from 'react-native-web-refresh-control'
import { useFocusEffect } from '@react-navigation/native';
import useCountSeconds from './useCountSeconds';
import ListItem from './ListItem';
const RefreshControl = Platform.OS === 'web'
? WebRefreshControl
:RNRefreshControl
export default function HomeScreen({ navigation }) {
const [data, setData] = useState([]);
const [isLoading, setIsLoading] = useState(false);
const flatlistRef = useRef();
// counts seconds between lastRefresh and current time
const { seconds, lastRefresh } = useCountSeconds(Date.now());
const refreshData = useCallback(async () => {
setIsLoading(true);
try {
// get sample data
const data = await fetch('https://dummyjson.com/products');
const json = await data.json();
setData(json.products);
// update lastRefresh
lastRefresh.current = Date.now();
setIsLoading(false);
} catch (err) {
console.log(err);
setIsLoading(false);
}
}, [lastRefresh]);
useFocusEffect(
// must wrap function in callback to avoid
// calling this effect alot
useCallback(() => {
console.log('Home screen focused');
refreshData();
flatlistRef.current?.scrollToOffset({ offset: 0 });
}, [refreshData])
);
// listen for Home tab presses
useEffect(()=>{
const unsubscribe = navigation.addListener('tabPress',e=>{
if(e.target.includes('Home')){
console.log(e)
refreshData()
}
})
return ()=>{
unsubscribe()
}
},[navigation,refreshData])
return (
<View style={styles.container}>
<Text>Refreshed: {seconds}s ago</Text>
<View style={styles.listContainer}>
<FlatList
contentContainerStyle={{paddingTop:Platform.select({
web:20,
default:0
})}}
ref={flatlistRef}
data={data}
renderItem={(props) => <ListItem {...props} />}
keyExtractor={(item) => item.id}
numColumns={2}
refreshControl={
<RefreshControl refreshing={isLoading} onRefresh={refreshData} />
}
/>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
width: '100%',
alignItems: 'center',
justigyContent: 'center',
},
listContainer: {
flex: 1,
width: '100%',
margin: 10,
padding: 5,
},
});