I am building a react-native app and seems I have a problem with the useFocusEffect ?
When the user opens the app, it displays a popup that prompts him to grant the write_settings_permission. As soon as the user returns back to the app screen, it should check if the permission was successfully granted and in that case navigate to a new screen, otherwise keep showing the popup.
import React, {useEffect, useState} from 'react';
import {View, Text, ActivityIndicator, Alert} from 'react-native';
import {useNavigation, useFocusEffect} from '@react-navigation/native';
import HotspotManager, {TetheringError} from '@react-native-tethering/hotspot';
const FirstScreen = () => {
const [loading, setLoading] = useState(true);
const [showPermissionsPopup, setShowPermissionsPopup] = useState(false);
const [permissionsGranted, setPermissionsGranted] = useState(false);
const navigation = useNavigation();
const requestWriteSettingsPermission = async () => {
try {
await HotspotManager.openWriteSettings();
const granted = await HotspotManager.isWriteSettingsGranted();
setPermissionsGranted(granted);
} catch (error) {
if (error instanceof TetheringError) {
console.log(error.message);
}
console.log(error);
}
};
const checkPermissions = async () => {
try {
const granted = await HotspotManager.isWriteSettingsGranted();
console.log(
`Write settings permission is ${granted ? 'granted' : 'not granted'}`,
);
setPermissionsGranted(granted);
} catch (error) {
if (error instanceof TetheringError) {
console.log(error.message);
}
console.log(error);
}
};
useFocusEffect(
React.useCallback(() => {
checkPermissions();
console.log('test1');
}, []),
);
useEffect(() => {
const timeout = setTimeout(() => {
setLoading(false);
setShowPermissionsPopup(true);
}, 2000);
return () => {
clearTimeout(timeout);
};
}, []);
useEffect(() => {
if (permissionsGranted) {
console.log('test2');
navigation.navigate('Network');
}
}, [navigation, permissionsGranted]);
return (
<View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
{loading ? (
<ActivityIndicator size="large" color="blue" />
) : (
<Text>Welcome to My App!</Text>
)}
{showPermissionsPopup && !permissionsGranted && (
<View
style={{
position: 'absolute',
top: 0,
bottom: 0,
left: 0,
right: 0,
backgroundColor: 'rgba(0, 0, 0, 0.5)',
justifyContent: 'center',
alignItems: 'center',
}}>
<View style={{backgroundColor: 'white', padding: 20}}>
<Text>Please grant the required permissions to continue.</Text>
<Text
style={{color: 'blue', textDecorationLine: 'underline'}}
onPress={requestWriteSettingsPermission}>
Grant Permissions
</Text>
</View>
</View>
)}
</View>
);
};
export default FirstScreen;
It works just fine, except the part that when I navigate back to the app from the settings, I have to press the "Grant the required Permissions" again, navigate to settings, go back to the app and only then it seems to work, at which point I am being redirected to the new screen.
What am I missing?
All I can think of is that the checkPermissions function is not being called when the user returns to the app because the focus effect hook is not triggered in that scenario, but I am failing to make it work even in that case.
I did find a somewhat similar error in the topics, but it didn’t seem to have a solution as the creator of the question solved it himself.
2
Answers
Try removing the React.useCallback wrapper to see if that solves the problem.
You are right, you need to use
AppState
https://github.com/react-native-community/hooks#useappstate