i'm pretty new on React Native and currently i am developing an app using expo. I am using TopTabNavigator from react navigation 6 and i don't understand how to reduce the no of the requests. Basically, whenever i hit a certain tab the request is made. (because the component is recreated - even if i come back on previous tab which is the same, no data modified). I tried to use useFocusEffect from react navigation but it does not work as i expected. Maybe i should make the requests in the ProfileTabsScreen and pass the data via props to the particular tabs?
MAIN COMPONENT
const ProfileStatsScreen = (props) => {
const { userId } = props.route.params;
const { initialRoute, username } = props.route.params;
const RatingsDetails = () => <RatingsTab userId={userId} />;
const FollowersDetails = () => <FollowersTab userId={userId} />;
const FollowingsDetails = () => <FollowingsTab userId={userId} />;
return (
<SafeAreaView style={styles.screen}>
<Header title={username} />
<TopTabContainer initialRouteName={initialRoute}>
<Tab.Screen
name="Ratings"
component={RatingsDetails}
options={{ tabBarLabel: "Reviews" }}
/>
<Tab.Screen
name="Followers"
component={FollowersDetails}
options={{ tabBarLabel: "Followers" }}
/>
<Tab.Screen
name="Following"
component={FollowingsDetails}
options={{ tabBarLabel: "Followings" }}
/>
</TopTabContainer>
</SafeAreaView>
);
};
TAB COMPONENT (RATINGS)
export const RatingsTab = ({ userId }) => {
const { user } = useAuth();
const [reviews, setReviews] = useState([]);
const [loading, setLoading] = useState(false);
useFocusEffect(
React.useCallback(() => {
setLoading(true);
axios
.get(`${process.env.BASE_ENDPOINT}/users/${userId}/reviews`, {
headers: { Authorization: `Bearer ${user?.token}` },
})
.then((res) => {
setReviews(res.data.reviews);
setLoading(false);
})
.catch((err) => {
console.log(err);
setLoading(false);
});
setLoading(false);
}, [userId, user?.token])
);
const renderRatings = ({ item }) => {
const { reviewer, rating, review, createdAt } = item;
return (
<CardRatings
avatar={reviewer?.avatar}
name={reviewer?.name}
date={moment(createdAt).format("LL")}
rating={rating}
review={review}
service={"Tuns"}
/>
);
};
return (
<>
{!loading && (
<FlatList
data={reviews}
keyExtractor={(item) => item?._id}
renderItem={renderRatings}
/>
)}
{loading && <Spinner />}
</>
);
};
You're very close to the solution, your useFocusEffect is configured properly. Change the lines
to read
i.e., if loading is true, don't make the axios call. While this doesn't eliminate the possibility of extra requests, it should reduce what you're seeing by quite a bit.
Also, since you're using .then, wrap the final line of your callback in .finally.
Otherwise, your loading state will be set to false before the promise resolves.