为什么在本机反应中未定义初始状态?

时间:2021-04-25 06:45:41

标签: javascript reactjs react-native react-hooks react-state

嗨!我是 React Native 的新手。最近我开发了一个可以正常工作的 expo 应用程序,但是我的登录屏幕面临一个问题是,当我第一次尝试输入用户名和密码时按下登录按钮,当我控制台记录数据设置的状态时AsyncStorage 帮助我在登录后进行处理,但这些状态未定义。第二次按下登录成功。

国家这种行为的原因是什么?

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

我遇到了这些状态的问题,

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

2 个答案:

答案 0 :(得分:1)

    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)

不等待 getKeysData 会导致问题。该函数将在 AsyncStorage.get 返回之前继续执行。即使您确实在等待它,反应状态也会在下一次渲染时更新,而不是立即更新。

但是,看起来 role 和 isLoggedIn 甚至没有在您的组件中使用,仅在登录功能中使用。因此,将它们改为局部变量并将它们从反应状态中移除。

答案 1 :(得分:0)

通过在钩子的参数中传递一些东西来设置初始值

例如

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