Skip to content
Advertisement

Why Initial states are undefined in react native?

Hy! I’m a newbie in react native. Recently I developed an expo app that is working properly but there is an issue I’m facing with my login screen is that when I put username and password press login button on the first attempt when I console log the states in which data are set with AsyncStorage which help me to do process after login but these states are undefined. On second press login success.

What’s the reason for this behavior of the state?

import React, { useState, useEffect } from 'react';
import { StyleSheet, Text, View, TextInput, Button, ScrollView } from 'react-native';
import { Card } from "react-native-shadow-cards";
import Constants from 'expo-constants';
import axios from 'react-native-axios';
import AsyncStorage from '@react-native-async-storage/async-storage';


const Login = ({ navigation }) => {
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');
  const [isLoggedIn,setIsLoggedIn] = useState();
  const [role, setRole] = useState();
  const [auth, setAuth] = useState('false');

  const authCred = {
    "username": username,
    "password": password,
  }
  console.log(authCred);

  const login = async () => {     
    try{
      const resp = await axios.post("https://hebruapp.herokuapp.com/api/login/", authCred);
     
    const designation = String(resp.data.role)
    
    //await AsyncStorage.setItem('isLoggedIn', '1')
    await AsyncStorage.multiSet([['isLoggedIn', '1'], ['role', designation]])
  
    const dataKeys =['isLoggedIn', 'role'];

    const getKeysData = async (keys) => {
        const stores = await AsyncStorage.multiGet(keys);
        const aData = stores.map(([key, value]) => ({[key]: value})) 
        setIsLoggedIn(aData[0]['isLoggedIn'])
        setRole(aData[1]['role'])
    }
    getKeysData(dataKeys)
    
    console.log('keystart')
    console.log(isLoggedIn)
    console.log(role)
    console.log('keyend')
    if (isLoggedIn == '1'){
        if(role == 'true'){
            console.log('adminSide')
            navigation.navigate('App');
            navigation.navigate('Data',{
              role:true
            });
        }else if(role == 'false'){
          console.log('userSide')
            navigation.navigate('UserApp');
            navigation.navigate('Data',{
              role:false
            });
        }
    }else{
        navigation.navigate('Auth');
    }
    }catch(error){
      if(error.response){
        console.log('Username is incorrect')
        alert("Username/Password is incorrect");
        setUsername('');
        setPassword('')
      }
    }
    
  }





  return (
    <ScrollView>
      <Card style={styles.containerLogin} >
        <Text style={styles.titlePage}>Login</Text>

        <Text style={styles.bold}>Username:</Text>
        <TextInput
          style={styles.textinput}
          placeholder="Type a email"
          onChangeText={username => setUsername(username)}
          defaultValue={username}
        />

        <Text style={[styles.bold, styles.password]}>Password:</Text>
        <TextInput
          style={styles.textinput}
          placeholder="Type a password"
          onChangeText={password => setPassword(password)}
          defaultValue={password}
          secureTextEntry={true}
        />

        <View style={styles.loginButton} >
          <Button color="black" title="Login" onPress={()=>{login()}} />
        </View>

      </Card>
    </ScrollView>
  )
}

const styles = StyleSheet.create({
  containerLogin: {
    flex: 1,
    backgroundColor: "radial-gradient(ellipse at left bottom,    rgb(163, 237, 255) 0%,    rgba(57, 232, 255, 0.9) 59%,    rgba(48, 223, 214, 0.9) 100% )",
    marginVertical: 125,
    marginLeft: 20,
    paddingLeft: 30,
    paddingRight: 30,
    alignItems: 'center',
    justifyContent: 'center',
    borderRadius: 60,

  },
  textinput: {
    height: 40,
    width: 250,
    borderColor: 'gray',
    borderWidth: 1,
    padding: 10,
    backgroundColor: 'white',
  },
  bold: {
    fontWeight: 'bold',
    justifyContent: 'center',
  },
  titlePage: {
    fontWeight: 'bold',
    fontSize: 30,
    marginBottom: 20
  },
  password: {
    margin: 20,
    marginBottom: 0,
  },
  loginButton: {
    marginTop: 25,
  },
  link: {
    marginTop: 10,
  },
  linkSignup: {
    marginTop: 8,
    textDecorationLine: 'underline',
    color: 'white',
  }
})
export default Login

I’m facing an issue with these states,

  const [isLoggedIn,setIsLoggedIn] = useState();
  const [role, setRole] = useState();

Advertisement

Answer

    const getKeysData = async (keys) => {
        const stores = await AsyncStorage.multiGet(keys);
        const aData = stores.map(([key, value]) => ({[key]: value})) 
        setIsLoggedIn(aData[0]['isLoggedIn'])
        setRole(aData[1]['role'])
    }
    getKeysData(dataKeys)

Not awaiting getKeysData is going to cause problems. The function will continue executing before the AsyncStorage.get comes back. Even if you did await it, the react state would be updated on the next render, not immediately.

However, it looks like role and isLoggedIn aren’t even used in your component, only in the login function. So make them local variables instead and remove them from react state.

User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement