简体   繁体   English

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

[英]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.最近我开发了一个 expo 应用程序,该应用程序工作正常,但我的登录屏幕面临的一个问题是,当我输入用户名和密码时,在第一次尝试时按下登录按钮,当我控制台记录设置数据的状态时AsyncStorage 帮助我在登录后进行处理,但这些状态是未定义的。 On second press login success.第二次按登录成功。

What's the reason for this behavior of the state? 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();
    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.不等待 getKeysData 会导致问题。 The function will continue executing before the AsyncStorage.get comes back. function 将在 AsyncStorage.get 返回之前继续执行。 Even if you did await it, the react state would be updated on the next render, not immediately.即使您确实等待它,反应 state 也会在下一次渲染时更新,而不是立即更新。

However, it looks like role and isLoggedIn aren't even used in your component, only in the login function.但是,看起来角色和 isLoggedIn 甚至没有在您的组件中使用,仅在登录 function 中使用。 So make them local variables instead and remove them from react state.因此,将它们改为局部变量并将它们从反应 state 中删除。

Set the initial values by passing something in the param of the hook通过在钩子的参数中传递一些东西来设置初始值

For example,例如,

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM