Javascript 使用redux和asyncStorage在react native中进行身份验证和授权

Javascript 使用redux和asyncStorage在react native中进行身份验证和授权,javascript,android,reactjs,react-native,redux,Javascript,Android,Reactjs,React Native,Redux,我是react native和react redux的新手。我正在做一个react本地项目,我想在其中实现身份验证和授权。在几毫秒内,我想显示splashscreen,若用户未登录,则重定向到登录页面,否则重定向到仪表板页面。如果用户注销,则导航到登录屏幕。我使用的是react native 0.62、react navigation 5.x和redux 7.2。我已经为登录屏幕、忘记密码屏幕、otp屏幕和重置密码屏幕创建了一个stacknavigator。一个抽屉提示器,用于抽屉,包括仪表板屏

我是react native和react redux的新手。我正在做一个react本地项目,我想在其中实现身份验证和授权。在几毫秒内,我想显示splashscreen,若用户未登录,则重定向到登录页面,否则重定向到仪表板页面。如果用户注销,则导航到登录屏幕。我使用的是react native 0.62、react navigation 5.x和redux 7.2。我已经为登录屏幕、忘记密码屏幕、otp屏幕和重置密码屏幕创建了一个stacknavigator。一个抽屉提示器,用于抽屉,包括仪表板屏幕、lms屏幕、我的个人资料屏幕和注销。我已经使用redux thunk实现了api。我无法重定向到仪表板。目前,我已经用UseStatic检查了使用静态值的条件。我不知道这是否正确。我已在登录屏幕中选中“记住我”复选框。因此,如果用户选中该复选框,则在用户注销之前,用户不需要输入凭据。 我筋疲力尽,因为我没有得到什么是redux和asyncStorage,以及如何使用它

App.js file
import 'react-native-gesture-handler';
enableScreens();
import React, { useState, useEffect } from 'react';
import { enableScreens } from 'react-native-screens';
import { StatusBar } from 'react-native';
import { Provider, connect } from 'react-redux';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';

import store from '../store/store';
import SplashScreen from '../screens/splashScreen';
import MainStack  from '../routes/MainStack';
import MainNavigator  from '../routes/MainNavigator';


const RootStack = createStackNavigator();

const App = () => {
  const [isLoading, setIsLoading] = useState(true);
  const [auth, setAuth] = useState(false);

  useEffect(() => {
    setTimeout(async () => {
      setIsLoading(!isLoading);
      setAuth(false);  
    }, 2000)
  }, []);



  return (
    <Provider store={store}>
      <NavigationContainer>
        <StatusBar backgroundColor={isLoading ? '#000000' : '#F3F3F3'} />
                {isLoading ?
          
            <SplashScreen/>:
            auth ?
            <MainNavigator/>
           
              :
              <MainStack />
             
      </NavigationContainer>
    </Provider>
  );
  //}
}


export default App;

MainStack.js File

export default ({navigation}) => {
  return (
    <Stack.Navigator initialRouteName="Login" screenOptions={{
      headerShown: false
    }}>
      <Stack.Screen name="Login" component={Login}/>
      <Stack.Screen name="ForgotPassword" component={ForgetPassword}/>
      <Stack.Screen name="VerifyOTP" component={VerifyOTP} />
      <Stack.Screen name="ResetPassword" component={ResetPassword} />      
    </Stack.Navigator>
  );
};

MainNavigator.js
const DashboardStackScreen = ({ navigation }) => {
  return (
    <DashboardStack.Navigator screenOptions={{
      headerTitle: 'Good Morning, John',
      header: props => <GradientHeader {...props} />,
     
      headerLeft: () => (
        <TouchableOpacity onPress={navigation.openDrawer} style={{padding: 20}}>
          <Image source={require('../assets/images/menu_bar.png')} style={{width:18, height:12}}/>
        </TouchableOpacity>
      ),
      headerTransparent: true,
      headerStyle: {
        backgroundColor:  'transparent' 
      },
      headerTintColor: '#fff',    
      headerTitleStyle: { fontFamily: 'OpenSans-SemiBold', fontSize: 20},
    }}>
      <DashboardStack.Screen name="Dashboard" component={Dashboard} />
    </DashboardStack.Navigator>
  );
}

export default({navigation}) =>{
  return (
    <Drawer.Navigator initialRouteName="Dashboard" drawerContent={(props) => <DrawerContent {...props} />} hideStatusBar={false} focused={true} labelStyle={{ fontSize: 14, fontFamily: 'OpenSans-SemiBold' }} drawerContentOptions={{ activeBackgroundColor: "#F1F1F1", activeTintColor: "#000000", inactiveTintColor: "#818181",itemStyle: { marginLeft:0, paddingHorizontal: 10,width:'100%',  borderRadius: 0}}} 
    
   >
      <Drawer.Screen name="Dashboard" component={DashboardStackScreen} options={{
        drawerIcon: ({ focused, size }) => (
          <Image source={require('../assets/images/dashboard.png')} style={{ height: 17.78, width: 16}}  resizeMode="contain"/>
        ),
      }}
      
      />
      <Drawer.Screen name="My Profile" component={MyProfileStackScreen} options={{
        drawerIcon: ({ focused, size }) => (
          <Image source={require('../assets/images/profile.png')} style={{ height: 16, width: 16 }}  resizeMode="contain"/>
        ),
      }} />
     
      <Drawer.Screen name="LMS" component={LmsStackScreen} options={{
        drawerIcon: ({ focused, size }) => (
          <Image source={require('../assets/images/lms.png')} style={{ height: 14.46, width: 16 }}  resizeMode="contain"/>
        ),
      }} />
      <Drawer.Screen name="Change Password" component={ChangePasswordStackScreen} options={{
        drawerIcon: ({ focused, size }) => (
          <Image source={require('../assets/images/key.png')} style={{ height: 8.73, width: 16 }}  resizeMode="contain"/>
        ),
      }} />
    </Drawer.Navigator>
  );
};

Login.js 
import React from 'react';
import { connect } from 'react-redux';
import LinearGradient from 'react-native-linear-gradient';
import { ScrollView, KeyboardAvoidingView, View, Text, Image, TextInput, TouchableOpacity, SafeAreaView, Keyboard, TouchableWithoutFeedback } from 'react-native';
import Toast from 'react-native-simple-toast';
/* import CheckBox from '@react-native-community/checkbox'; */
/* import CheckBox from 'react-native-check-box'; */
import Checkbox from 'react-native-custom-checkbox';

import styles from '../utility/styles';
import { thunk_login_creator } from '../actions/login';

class Login extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      color: "#ffffff",
      isSelected: false,
      isPasswordHidden: true,
      employeeId: '',
      employeeIdError: '',
      password: '',
      passwordError: ''
    }
  }

  handleValidation(type) {
    let obj = this.state;
    switch (type) {
      case 'employeeId':
        obj.employeeIdError = this.state.employeeId.trim() == "" ? "Employee ID is required" : "";
        break;
      case 'password':
        obj.passwordError = this.state.password.trim() == "" ? "Password is required" : ""
        break;
      default:
        break;
    }
    this.setState({ obj });
  }

  handleChange(type, text) {
    if (type == 'employeeId') {
      this.setState({ employeeId: text.trim() }, () => {
        this.handleValidation(type);
      });
    } else {
      this.setState({ password: text.trim() }, () => {
        this.handleValidation(type);
      });
    }
  }

  handlePasswordToggle = () => {
    console.log('handlePasswordToggle called');
    this.setState({ isPasswordHidden: !this.state.isPasswordHidden })
  }

  handleRememberMe = () => {
    console.log('handleRememberMe called');
    this.setState({ isSelected: !this.state.isSelected }, () => {
      if (this.state.isSelected == true) {
        this.setState({ color: "red" });
      } else {
        this.setState({ color: "black" });
      }
      console.log('remember me--->', this.state.isSelected);
    })
  }

  handleLogin = () => {
    console.log('handleLogin called')
    this.props.dispatch(thunk_login_creator({ 'empId': this.state.employeeId, 'password': this.state.password, 'isRemembered': this.state.isSelected },/* ()=>{
      if (this.props.data.login.loading) {
        Toast.show('Loading...');
      } else if (this.props.data.login.error) {
        Toast.show('Invalid Credentials');
      } else {
        this.setState({
          employeeId: '',
          employeeIdError: '',
          password: '',
          passwordError: ''
        }, () => {
           this.props.navigation.navigate('Dashboard') 
        })
      }
    } */));
     if (this.props.data.login.loading) {
      Toast.show('Loading...');
    } else if (this.props.data.login.error != '') {
      Toast.show(this.props.data.login.error);
    } else {
      this.setState({
        isSelected: false,
        employeeId: '',
        employeeIdError: '',
        password: '',
        passwordError: ''
      }, () => {
        //this.props.navigation.navigate('Dashboard')
      })
    } 
  }

  render() {
    return (

      <SafeAreaView style={styles.baseContainer}>

        <KeyboardAvoidingView behaviour="padding" style={styles.baseContainer} >
          <TouchableWithoutFeedback style={styles.baseContainer} onPress={Keyboard.dismiss}>

            <View style={styles.baseContainer} >
              <View style={styles.ovalContainer}>
                <View style={styles.oval1} />
                <View style={styles.oval2} />
                <View style={styles.logoContainer}>
                  <Image source={require('../assets/images/MJB_Logo.png')} style={styles.logo} />
                </View>
              </View>
              <View style={styles.formContainer}>
                <View style={styles.loginTextContainer}>
                  <Text style={styles.loginText}>Login</Text>
                </View>
                <View style={styles.loginFormContainer}>
                  <View>
                    <Text style={styles.labelText}>Employee ID</Text>
                    <TextInput style={styles.inputField} value={this.state.employeeId} placeholder="" onBlur={() => this.handleValidation('employeeId')} keyboardType="email-address" returnKeyType="next" autoCorrect={false} onSubmitEditing={() => this.refs.txtPassword.focus()} onChangeText={(text) => this.handleChange('employeeId', text)} />
                    <Text style={styles.errorText} >{this.state.employeeIdError}</Text>
                  </View>
                  <View>
                    <Text style={styles.labelText}>Password</Text>
                    <View>
                      <TextInput style={styles.inputField} value={this.state.password} onBlur={() => this.handleValidation('password')}
                        placeholder="" returnKeyType="go" secureTextEntry={this.state.isPasswordHidden} autoCorrect={false} ref={"txtPassword"} onChangeText={(text) => this.handleChange('password', text)} />
                      <TouchableWithoutFeedback onPress={this.handlePasswordToggle} style={styles.eyeIconContainer}>
                        <Image source={this.state.isPasswordHidden
                          ? require('../assets/images/eye_on.png')
                          : require('../assets/images/eye_off.png')} style={styles.eyeIcon} resizeMode="contain" />
                      </TouchableWithoutFeedback>
                    </View>
                    <Text style={styles.errorText} >{this.state.passwordError}</Text>
                  </View>
                  {/* 
                  <View style={styles.rememberMeContainer}>
                      <CheckBox 
                        value={this.state.isSelected}
                        onValueChange={this.handleRememberMe}
                        style={styles.checkbox}
                        tintColors={{ true: '#6CCFF6', false: '#CED4DA' }}
                        onFillColor="#6CCFF6"
                        onTintColor="#6CCFF6"
                      />
                      <Text style={styles.rememberMeText}>Remember Me</Text>
                    </View>
                  */}

                  <View style={styles.rememberMeContainer}>
                    {/*  <CheckBox 
                        isChecked={this.state.isSelected}
                        onClick={this.handleRememberMe}
                       style={styles.checkbox}
                        checkBoxColor="#CED4DA"
                        checkedCheckBoxColor="#6CCFF6"
                       
                      /> */}
                    <Checkbox
                      checked={this.state.isSelected}
                      style={{/* backgroundColor: (this.state.isSelected ? 'green':'black'), */ color: '#000000', borderRadius: 3, borderColor: '#CED4DA', borderWidth: 1 }}
                      size={25}
                      onChange={this.handleRememberMe} />
                    <Text style={styles.rememberMeText}>Remember Me</Text>
                  </View>

                  <TouchableOpacity disabled={this.state.employeeId == '' || this.state.password == '' ? true : false} onPress={this.handleLogin} >
                    <LinearGradient start={{ x: 0, y: 0 }} end={{ x: 1, y: 0 }} colors={['#6CCFF6', '#596AB2']} style={styles.linearGradient}>
                      <Text style={styles.buttonText}>
                        Login
                      </Text>
                    </LinearGradient>
                  </TouchableOpacity>
                  <View style={styles.forgetPasswordTextContainer} >
                    <Text style={styles.forgetText}>Forgot password? <Text style={styles.resetText} onPress={() =>
                      this.props.navigation.navigate('ForgotPassword')
                    }> Reset</Text></Text>
                  </View>
                </View>
                {/* <View style={styles.forgetPasswordTextContainer}>
                  <Text style={styles.forgetText}>Forgot password? <Text style={styles.resetText} onPress={() =>
                    this.props.navigation.navigate('ForgotPassword')
                  }> Reset</Text></Text>
                </View> */}
              </View>
            </View>

          </TouchableWithoutFeedback >
        </KeyboardAvoidingView>

      </SafeAreaView>

    )
  }
};

const mapStateToProps = state => {
  console.log('login state===>', state)
  return {
    data: state
  };
};
export default connect(mapStateToProps)(Login);


Any help is appreciated. 
App.js文件
导入“反应本机手势处理程序”;
启用屏幕();
从“React”导入React,{useState,useffect};
从“react native screens”导入{enableScreens};
从“react native”导入{StatusBar};
从'react redux'导入{Provider,connect};
从'@react-navigation/native'导入{NavigationContainer};
从'@react navigation/stack'导入{createStackNavigator};
从“../store/store”导入存储;
从“../screens/SplashScreen”导入SplashScreen;
从“../routes/MainStack”导入MainStack;
从“../routes/MainNavigator”导入MainNavigator;
const RootStack=createStackNavigator();
常量应用=()=>{
const[isLoading,setIsLoading]=useState(true);
const[auth,setAuth]=useState(false);
useffect(()=>{
setTimeout(异步()=>{
设置isLoading(!isLoading);
setAuth(假);
}, 2000)
}, []);
返回(
{孤岛加载?
:
啊?
:
);
//}
}
导出默认应用程序;
MainStack.js文件
导出默认值({navigation})=>{
返回(
);
};
MainNavigator.js
const DashboardStackScreen=({navigation})=>{
返回(
,
标题左侧:()=>(
),
校长:是的,
头型:{
背景颜色:“透明”
},
标题颜色:“#fff”,
headerTitleStyle:{fontFamily:'OpenSans SemiBold',fontSize:20},
}}>
);
}
导出默认值({navigation})=>{
返回(
}hideStatusBar={false}focused={true}labelStyle={{fontSize:14,fontFamily:'OpenSans SemiBold'}}drawerContentOptions={{activeBackgroundColor:'F1F1F1',activeTintColor:'000000',InactiveIntColor:'818181',itemStyle:{marginLeft:0,paddingHorizontal:10,宽度:'100%,边界半径:0}}
>
(
),
}}
/>
(
),
}} />
(
),
}} />
(
),
}} />
);
};
Login.js
从“React”导入React;
从'react redux'导入{connect};
从“反应本机线性渐变”导入LinearGradient;
从“react native”导入{ScrollView,KeyboardAvoidingView,View,Text,Image,TextInput,TouchableOpacity,SafeAreaView,Keyboard,TouchableWith Outfeedback};
从“react native simple Toast”导入Toast;
/*从“@react native community/CheckBox”导入复选框*/
/*从“反应本机复选框”导入复选框*/
从“反应本机自定义复选框”导入复选框;
从“../utility/styles”导入样式;
从“../actions/login”导入{thunk_login_creator};
类登录扩展了React.Component{
建造师(道具){
超级(道具);
此.state={
颜色:“ffffff”,
选:错,
isPasswordHidden:对,
雇员ID:“”,
员工ID错误:“”,
密码:“”,
密码错误:“”
}
}
扶手电梯(类型){
设obj=this.state;
开关(类型){
案例“employeeId”:
obj.employeeIdError=this.state.employeeId.trim()==“”?“需要员工ID”:“”;
打破
案例“密码”:
obj.passwordError=此.state.password.trim()==“”?“需要密码”:”
打破
违约:
打破
}
this.setState({obj});
}
handleChange(类型、文本){
如果(类型=='employeeId'){
this.setState({employeeId:text.trim()},()=>{
这是一种手动电梯(类型);
});
}否则{
this.setState({密码:text.trim()},()=>{
这是一种手动电梯(类型);
});
}
}
handlePasswordToggle=()=>{
log('handlePasswordToggle called');
this.setState({isPasswordHidden:!this.state.isPasswordHidden})
}
handleRememberMe=()=>{
log('handleRememberMe called');
this.setState({isSelected:!this.state.isSelected},()=>{
if(this.state.isSelected==true){
this.setState({color:“red”});
}否则{
this.setState({color:“black”});
}
console.log('记住我-->',this.state.isSelected);
})
}
handleLogin=()=>{
console.log('调用handleLogin')
this.props.dispatch(thunk_login_creator({'empId':this.state.employeeId,'password':this.state.password,'isremembeed':this.state.isSelected},/*()=>{
if(this.props.data.login.load){
Toast.show('Loading…');
}else if(this.props.data.login.error){
Toast.show(“无效凭据”);
}否则{
这是我的国家({
雇员ID:“”,
员工ID错误:“”,
密码:“”,
密码错误:“”
}, () => {