skip to Main Content

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


  1. Try removing the React.useCallback wrapper to see if that solves the problem.

    useFocusEffect(() => {
      checkPermissions();
      console.log('test1');
    });
    
    Login or Signup to reply.
  2. 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.

    You are right, you need to use AppState https://github.com/react-native-community/hooks#useappstate

    // imports
    import {useAppState} from '@react-native-community/hooks'
    
    
    // start of the component
    const currentAppState = useAppState()
    
    
    // new code
    useEffect(() => {
      if (currentAppState === 'active') {
        checkPermissions();
      }
    }, [currentAppState]);
    
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search