I'm facing a strange issue in a React Native app where an API request sometimes gets triggered twice after the app comes back from the background.
It seems to happen mostly on Android. On the initial screen load everything works normally.
I have a screen where I fetch the latest data when the screen is focused:
const fetchData = async () => {
try {
console.log('API CALLED');
const response = await api.get('/dashboard');
setData(response.data);
} catch (error) {
console.log('API error:', error);
}
};
useFocusEffect(
useCallback(() => {
fetchData();
return () => {
console.log('Screen unfocused');
};
}, [])
);
Normally I get:
API CALLED
only once.
But if I:
Open this screen
Put the app in the background
Wait for a few seconds
Open the app again
I sometimes see:
API CALLED
API CALLED
and two requests appear in the network logs almost at the same time.
I initially thought the component was being mounted twice, so I added:
useEffect(() => {
console.log('MOUNTED');
return () => {
console.log('UNMOUNTED');
};
}, []);
But when the duplicate request happens, I don't always see the component unmounting/remounting.
I also checked that fetchData() isn't being called from another useEffect.
Environment
React Native: 0.81.x
React Navigation: 7.x
React: 19.x
Platform: Android
What I tried
I can prevent the duplicate request with a ref:
const isFetching = useRef(false);
const fetchData = async () => {
if (isFetching.current) return;
isFetching.current = true;
try {
const response = await api.get('/dashboard');
setData(response.data);
} finally {
isFetching.current = false;
}
};
This works as a guard, but I'm not sure if I'm just hiding the actual problem.
Can useFocusEffect run again when an Android app returns from the background even if the screen was never unmounted?
If so, what is the recommended pattern when I want to fetch once when navigating to the screen, but don't want duplicate requests when the app resumes?