React Native. Как отображать экраны в соответствии со статусом аутентификации пользователя

#firebase #react-native #redux #react-native-navigation #react-native-firebase

#firebase #реагировать-родной #сокращение #react-native-навигация #реагировать-родной-firebase

Вопрос:

Я разрабатываю свое первое в истории приложение React Native. Я создал экран входа / регистрации и подключил их к Firebase для аутентификации. А также у меня есть экран, содержащий ящики. Я хочу, чтобы, если пользователь не прошел проверку подлинности. Должен отображаться экран входа / регистрации, в противном случае будет отображаться рабочий стол (имеющий много ящиков). Для этого я выполнил некоторые проверки в MainRouteComponent, но он не работает

Я загружаю свой код всех связанных компонентов, а также некоторый код redux, который я использовал здесь. Я знаю, что потребуется время, чтобы просмотреть столько кода, но я много пробовал, и сейчас у меня проблемы. Надеюсь, многие из вас помогут. 🙂

Вот мой код:-

App.js

 import React from 'react';
import Main from './components/MainComponent';
import MainRoute from './components/MainRouteComponent'
import { Provider } from 'react-redux';
import { ConfigureStore } from './redux/configureStore';
import { PersistGate } from 'redux-persist/es/integration/react'
import { Loading } from './components/LoadingComponent';

const { persistor, store } = ConfigureStore();
export default App  = () =>{
    return (
      <Provider store={store}>
        <PersistGate 
          loading={<Loading />}
          persistor={persistor}>
            <MainRoute/>
        </PersistGate>
      </Provider>
    );
}
  

MainRouteComponent.js

 import React, { useState } from 'react';
import Main from './MainComponent';
import Root from './RootComponent';
import { auth } from '../firebase/firebase';

const AuthContext = React.createContext();

const MainRoute = () => {
    const user = auth.currentUser
    console.log("User", user)
    console.log("Auth", isAuth)
    return(
            {(user == null) ?
                <Root />
                :
                <Main />
            } 
    )
}

export default MainRoute;
  

RootComponent.js

 import React, {Component} from 'react';
import { createStackNavigator } from 'react-navigation';
import * as Animatable from 'react-native-animatable';
import SplashScreen from './SplashScreen';
import Login from './LoginComponent';
import Register from './RegistrationComponent';

const RootStack = createStackNavigator({
    SplashScreen: { screen: SplashScreen,
            navigationOptions: ({ navigation }) => ({
                headerStyle: {
                    backgroundColor: "#512DA8"
                },
                headerTitle: "Welcome Foodies",
                headerTintColor: '#fff',
                headerTitleStyle: {
                    color: "#fff",
                    alignItems: 'center'         
                }          
            })  
          },
    LoginComponent: { 
        screen: Login,
        navigationOptions: ({ navigation }) => ({
            headerStyle: {
                backgroundColor: "#512DA8"
            },
            headerTitle: "Login",
            headerTintColor: '#fff',
            headerTitleStyle: {
                color: "#fff",
                alignItems: 'center'         
            }          
        })  
      },
    Register: { 
        screen: Register,
        navigationOptions: ({ navigation }) => ({
            headerStyle: {
                backgroundColor: "#512DA8"
            },
            headerTitle: "Sign Up",
            headerTintColor: '#fff',
            headerTitleStyle: {
                color: "#fff",
                alignItems: 'center'         
            }          
        })  
      },
    },
    
    {
      initialRouteName: 'SplashScreen',
      navigationOptions: ({ navigation }) => ({
          headerStyle: {
              backgroundColor: "#512DA8"
          },
          headerTintColor: '#fff',
          headerTitleStyle: {
              color: "#fff"            
          }
      })
  }
);

class Root extends Component {
    render() {
        return (
            <RootStack />
        )
    }
}

export default Root;
  

LoginComponent.js

 import React, { Component } from 'react';
import { View, StyleSheet, Text, ScrollView, Image } from 'react-native';
import { Input, CheckBox, Button, Icon } from 'react-native-elements';
import * as SecureStore from 'expo-secure-store';
import { loginUser} from '../redux/ActionCreators';
import { connect } from 'react-redux';

const mapStateToProps = state => {
    return {
      auth: state.AUTH
    }
}

const mapDispatchToProps = dispatch => {
    return {
        loginUser: (creds) => dispatch(loginUser(creds))
    }
}

class Login extends Component {

    constructor(props) {
        super(props);

        this.state = {
            email: '',
            password: '',
            remember: false
        }
    }

    componentDidMount() {
        SecureStore.getItemAsync('userinfo')
            .then((userdata) => {
                let userinfo = JSON.parse(userdata);
                if (userinfo) {
                    this.setState({email: userinfo.email});
                    this.setState({password: userinfo.password});
                    this.setState({remember: true})
                }
            })
    }

    static navigationOptions = {
        title: 'Login',
        tabBarIcon: ({ tintColor }) => (
            <Icon
              name='sign-in'
              type='font-awesome'            
              size={24}
              iconStyle={{ color: tintColor }}
            />
          ) 
    };

    handleLogin() {
        this.props.loginUser({email: this.state.email, password: this.state.password});
        //event.preventDefault();
        if (this.state.remember)
            SecureStore.setItemAsync('userinfo', JSON.stringify({email: this.state.email, password: this.state.password}))
                .catch((error) => console.log('Could not save user info', error));
        else
            SecureStore.deleteItemAsync('userinfo')
                .catch((error) => console.log('Could not delete user info', error));
        
        this.setState({
            email: '',
            password: '',
            remember: false
        })
        this.props.navigation.navigate('Home')
    }

    render() {
        const { navigate } = this.props.navigation;
        return (
            <View style={styles.container}>
                <Input
                    placeholder="Email"
                    leftIcon={{ type: 'font-awesome', name: 'envelope-o' }}
                    onChangeText={(email) => this.setState({email})}
                    value={this.state.email}
                    containerStyle={styles.formInput}
                    />
                <Input
                    placeholder="Password"
                    leftIcon={{ type: 'font-awesome', name: 'key' }}
                    onChangeText={(password) => this.setState({password})}
                    value={this.state.password}
                    containerStyle={styles.formInput}
                    />
                <CheckBox title="Remember Me"
                    center
                    checked={this.state.remember}
                    onPress={() => this.setState({remember: !this.state.remember})}
                    containerStyle={styles.formCheckbox}
                    />
                <View style={styles.formButton}>
                    <Button
                        onPress={() => this.handleLogin()}
                        title="Login"
                        icon={
                            <Icon
                                name='sign-in'
                                type='font-awesome'            
                                size={24}
                                color= 'white'
                            />
                        }
                        buttonStyle={{
                            backgroundColor: "#512DA8"
                        }}
                        />
                </View>
                <View style={styles.formButton}>
                    <Button
                        onPress={() => navigate('Register')}
                        title="Register"
                        clear
                        icon={
                            <Icon
                                name='user-plus'
                                type='font-awesome'            
                                size={24}
                                color= 'blue'
                            />
                        }
                        titleStyle={{
                            color: "blue"
                        }}
                        buttonStyle={{
                            backgroundColor: "transparent"
                        }}
                        />
                </View>
            </View>
        );
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(Login);
  

ActionCreator.js

 import * as ActionTypes from './ActionTypes';
import { auth, firestore, fireauth, firebasestore } from '../firebase/firebase';

export const requestLogin = () => {
    return {
        type: ActionTypes.LOGIN_REQUEST
    }
}
  
export const receiveLogin = (user) => {
    return {
        type: ActionTypes.LOGIN_SUCCESS,
        user
    }
}
  
export const loginError = (message) => {
    return {
        type: ActionTypes.LOGIN_FAILURE,
        message
    }
}

export const loginUser = (creds) => (dispatch) => {
    // We dispatch requestLogin to kickoff the call to the API
    dispatch(requestLogin(creds))

    return auth.signInWithEmailAndPassword(creds.email, creds.password)
    .then(() => {
        var user = auth.currentUser;
        dispatch(fetchFavorites());
        dispatch(receiveLogin(user));
    })
    .then(response => { console.log('Login Successful', response); alert('Thank you for login!'); })
    .catch(error => {console.log('Error', error); alert(error)})
    .catch(error => dispatch(loginError(error.message)))
};
  

У меня также есть Login Reducer как auth.js как я и думал, это может помочь в проверке подлинности для соответствующего отображения экрана.

auth.js

 import * as ActionTypes from './ActionTypes';

export const Auth = (state = {
        isLoading: false,
        isAuthenticated: false,
        user: null,
        errMess: null
    }, action) => {
    switch (action.type) {
        case ActionTypes.LOGIN_REQUEST:
            return {...state,
                isLoading: true,
                isAuthenticated: false,
            };
        case ActionTypes.LOGIN_SUCCESS:
            return {...state,
                isLoading: false,
                isAuthenticated: true,
                errMess: '',
                user: action.user
            };
        case ActionTypes.LOGIN_FAILURE:
            return {...state,
                isLoading: false,
                isAuthenticated: false,
                errMess: action.message
            };
        case ActionTypes.LOGOUT_REQUEST:
            return {...state,
                isLoading: true,
                isAuthenticated: true
            };
        case ActionTypes.LOGOUT_SUCCESS:
            return {...state,
                isLoading: false,
                isAuthenticated: false,
                token: '',
                user: null
            };
        default:
            return state
    }
}
  

Ответ №1:

Создайте отдельную маршрутизацию для экранов стека, которые вы не хотите показывать! Попробуйте сделать 2 стека!

Комментарии:

1. Братан, за раз уже отображается один экран. Я не включил здесь код основного экрана, поскольку он не имеет отношения к проблеме. Что я хочу сделать, так это то, что он должен автоматически отображать либо логин, либо главный экран в соответствии со статусом аутентификации пользователя