I am new to React Native and I am currently trying to fetch credential data from a website and save it into device memory. However I am encountering few issues regarding it!
My flow:
- When app is launched the app will check asyncStorage if there are credentials. 
- If so, we go straight into the app. Otherwise we enter the RootStackScreen(aka login Screen)*** (issue #1) 
- (LOGIN) A user will enter his/her login into text input which would be saved in a useState. 
- Using a function 'loginHandle' a fetch request is called using the info from useState and we setCredential with the data returned.** (issue #2) 
- The app should rerender and see that there is a credential and load into the main screen. *** (issue #3) 
However, I'm encountering 2 issues.
- *** Even when asyncStorage does contain the credentials when I check appLoad.credentials in the return(...) it returns a null. However, it returns the correct value in my useEffect(). I thought by using useEffect() I am calling the functions during ComponentsDidMount which is before the rendering of the screen. So shouldn't appLoad.credentials contain a string? 
- On my console.log(credential) It is always one step behind. I.e. I press the login button once. The console log will return null. However, I thought that since the console.log() is after the fetch command that the credentials should be set before the console.log call! 
- How do I get the app to rerender. I've seen online regarding force rerendering but I heard that it was bad! 
App.js
import AsyncStorage from '@react-native-community/async-storage';
...
export default function App() {
  const STORAGE_KEY = '@deviceCredentials';
  const [data, setData] = useState('');
  const appLoad = {
    isLoading: true,
    credentials: null
  };
  //Runs during ComponentsDidMount
  useEffect(() => {
    setTimeout(async () => {
      //In 1000ms try to get credentials
      try {
        appLoad.credentials = await AsyncStorage.getItem(STORAGE_KEY);
        console.log(appLoad.credentials);
      } catch (e) {
        console.log(e);
      }
    }, 1000);
  }, []);
  //Render
  return (
 
      <NavigationContainer>
        {/* If credentials is not null then we can go straight into Main screen, 
            otherwise we go to Login Screen */}
        {appLoad.credentials !== null ? (
          <Drawer.Navigator drawerContent={props => <DrawerContent {...props} />}>
            <Drawer.Screen name="MusteringDrawer" component={MainTabScreen} />
          </Drawer.Navigator>
        )
          :
          <RootStackScreen />
        }
      </NavigationContainer>
  );
};
SignIn.js
...
...
const [data, setData] = useState({
                               username: '',
                               password: '',
                               ...
})
const [credential, setCredential] = useState({ data: null });
const STORAGE_KEY = '@deviceCredentials';
...
...
//Handles user data
const handleValidUser = (val) => {
            setData({
                ...data,
                username: val,
            });
}
const loginHandle = () => {
        fetch(url + data.password + data.username)
            .then(x => x.text())
            .then(y => {
                setCredential({ data: y });
            });
            console.log(credential);
            AsyncStorage.setItem(STORAGE_KEY, credential);
    }
return( 
     <Text>Username</Text>
     <TextInput
        placeholder="Your Username"
        onChangeText={(val) => handleValidUser(val)}
        onEndEditing={(e) => handleValidUser(e.nativeEvent.text)}
      />
     <Text>Password</Text>
     <TextInput
         placeholder="Your Password"
         onChangeText={(val) => handlePasswordChange(val)}
      />
      <View style={styles.button}>
            <TouchableOpacity  onPress={() => { loginHandle(); }}>
                   <Text>Sign In</Text>
            </TouchableOpacity>
      </View>
 
    