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 />}
</>
);
};
CodePudding user response:
You're very close to the solution, your useFocusEffect is configured properly. Change the lines
useFocusEffect(
React.useCallback(() => {
setLoading(true);
to read
useFocusEffect(
React.useCallback(() => {
if (isLoading) return;
setLoading(true);
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.
.finally(()=> {
setLoading(false)
});
Otherwise, your loading state will be set to false before the promise resolves.
CodePudding user response:
Thank you, but unfortunately is not working. Let's assume that i am already in the RatingsTab and i have the data because by far the request was already made. If i go to FollowersTab and after that i come back to RatingsTab i don't want to make call if the data has not changed. if (isLoading) return;
i think it will not helping me, because the loading state is false at first (when the Ratings Tab component is re-created).