Как использовать createStackNavigator для создания разных домашних экранов на основе аутентификации? - PullRequest
0 голосов
/ 22 февраля 2020

Я использую React Native и хочу, чтобы пользователь выводился на другой домашний экран на основе аутентификации. Я использую Firebase в качестве базы данных, чтобы определить, является ли пользователь администратором или обычным пользователем. Как отправить пользователя на другой домашний экран в зависимости от отправленного им электронного письма?

Вот мое приложение. js код:

//downloaded libraries that allow different commands and tools
import React from 'react';
import {createAppContainer, createSwitchNavigator, Button, TouchableOpacity, Text} from 'react-navigation';
import {createStackNavigator} from 'react-navigation-stack';
import LoadingScreen from './screens/LoadingScreen';
import HomeScreen from './screens/HomeScreen';
import LoginScreen from './screens/LoginScreen';
import SurveyScreen from './screens/SurveyScreen';
import DetailsScreen from './screens/DetailsScreen'
import * as firebase from 'firebase';
import 'firebase/firestore';

//variable storing firebase api, authentication, and database keys
var firebaseConfig = {
    // excluded this part
};

//initializes firebase domain
firebase.initializeApp(firebaseConfig);

//navigation stacks for navigating between different screens
//one for user login (AuthStack) and the other for user screens (AppStack)
const AppStack = createStackNavigator({
  Home: {
    screen: HomeScreen,
    screen: Other
  },
  Survey: SurveyScreen,
  Details: DetailsScreen
})

const AuthStack = createStackNavigator({
  Login: {
    screen: LoginScreen,
    navigationOptions: {
      header: null
    },
  }
})

//exports navigation stacks to allow users to log in and navigate to different screens
//LoadingScreen.js is the first screen to load when app is initialized (initialRouteName: "Loading")
export default createAppContainer(
  createSwitchNavigator(
    {
      Loading: LoadingScreen,
      App: AppStack,
      Auth: AuthStack,
    },
    {
      initialRouteName: "Loading"
    }
  )
)
//navigation stacks for navigating between different screens
//one for user login (AuthStack) and the other for user screens (AppStack)
const AppStack = createStackNavigator({
  Home: {
    screen: HomeScreen,
    screen: Other
  },
  Survey: SurveyScreen,
  Details: DetailsScreen
})

const AuthStack = createStackNavigator({
  Login: {
    screen: LoginScreen,
    navigationOptions: {
      header: null
    },
  }
})

//exports navigation stacks to allow users to log in and navigate to different screens
//LoadingScreen.js is the first screen to load when app is initialized (initialRouteName: "Loading")
export default createAppContainer(
  createSwitchNavigator(
    {
      Loading: LoadingScreen,
      App: AppStack,
      Auth: AuthStack,
    },
    {
      initialRouteName: "Loading"
    }
  )
)

и вот мой LoginScreen. js код:

import React from 'react';
import {View, Text, StyleSheet, TextInput, TouchableOpacity, Image, KeyboardAvoidingView} from 'react-native';
import * as firebase from 'firebase';

export default class LoginScreen extends React.Component {
    //default states of values "email", "password", and "errorMessage"
    state = {
        email: "",
        password: "",
        errorMessage: null
    };

    componentDidMount() {
        console.disableYellowBox = true;
    }

    //function that logs user in and redirects them to the first screen in AppStack (HomeScreen.js)
    //if the correct email and password credentials are met. if credentials are not met, an error
    //message will be displayed
    handleLogin = () => {
        const {email, password} = this.state
        firebase
        .auth()
        .signInWithEmailAndPassword(this.state.email, this.state.password)
        .catch(error => this.setState({errorMessage: error.message}));
    };

    render() {
        //UI is coded in the return() area
        return (
            <KeyboardAvoidingView style={styles.container} behavior="padding" enabled>
                <Image style={styles.image}
                source={require('../assets/EMSlogo.png')}></Image>

                <View style={styles.errorMessage}>
                    {this.state.errorMessage && <Text style={styles.error}>{this.state.errorMessage}</Text>}
                </View>

                <View style={styles.form}>
                    <View>
                        <Text style={styles.inputTitle}>Email Address</Text>
                        <TextInput style={styles.input} autoCapitalize="none"
                        onChangeText={email => this.setState({ email })}
                        value={this.state.email}></TextInput>
                    </View>

                    <View style={{marginTop: 32}}>
                        <Text style={styles.inputTitle}>Password</Text>
                        <TextInput style={styles.input} secureTextEntry autoCapitalize="none"
                        onChangeText={password => this.setState({ password })}
                        value={this.state.password}></TextInput>
                    </View>
                </View>

                <TouchableOpacity style={styles.button} onPress={this.handleLogin}>
                    <Text style={{color: "#FFF", fontWeight: "500", fontSize: 21}}>
                        Sign In
                    </Text>
                </TouchableOpacity>
            </KeyboardAvoidingView>
        )
    }
}

//this is how you create a stylesheet in react native
const styles = StyleSheet.create({
    container: {
        flex: 1,
    },
    image: {
        margin: 30,
        marginBottom: 0,
        flex: 1,
        width: null,
        height: null,
        resizeMode: 'contain',
    },
    greeting: {
        marginTop: 32,
        fontSize: 18,
        fontWeight: "400",
        textAlign: "center"
    },
    errorMessage: {
        height: 72,
        alignItems: "center",
        justifyContent: "center",
        marginHorizontal: 30
    },
    error: {
        color: "#E9446A",
        fontSize: 16,
        fontWeight: "600",
        textAlign: "center"
    },
    form: {
        marginBottom: 48,
        marginHorizontal: 30,
    },
    inputTitle: {
        color: "#8A8F9E",
        fontSize: 16,
        textTransform: "uppercase"
    },
    input: {
        borderBottomColor: "#8A8F9E",
        borderBottomWidth: StyleSheet.hairlineWidth,
        height: 40,
        fontSize: 18,
        color: "#161F3D"
    },
    button: {
        marginHorizontal: 30,
        marginBottom: 35,
        backgroundColor: "#00235D",
        borderRadius: 4,
        height: 52,
        alignItems: "center",
        justifyContent: "center",
    }
});

Ответы [ 2 ]

0 голосов
/ 23 февраля 2020

Вы можете использовать компонент высокого порядка, который показывает экран входа в систему, если пользователь не аутентифицирован, в противном случае отобразите страницу администратора или базовую страницу на основе свойств компонента, например:

HO C component

import React, { Component } from 'react';

import Login from '../templates/login';

const AdminHOC = (props, Comp) => (WrappedComponent) => {
  return class LoaderHOC extends Component {
    render() {
      const { common: { user } } = this.props;
      const DefaultComponent = user ? Comp : Login;
      let valid = false;
      props.map((prop) => {
        if (user && user[prop]) {
          valid = true;
        }
        return true;
      });
      return valid
        ? (
          <WrappedComponent {...this.props} />
        )
        : (
          <DefaultComponent {...this.props} />
        );
    }
  };
};


export default AdminHOC;

Затем в компоненте вашей страницы администратора:

class Admin extends Component {
...
}

class Home extends Component {
...
}

// admin and development are props that needs to be true to render the admin page
// If both are false it shows a regular home page
export default AdminHOC(['admin', 'development'], Home)(Admin);

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

0 голосов
/ 23 февраля 2020

После входа перейдите к компоненту HomeScreen и используйте условный рендеринг в зависимости от типа пользователя. в вашем handleLogin проверьте тип пользователя и перейдите на главный экран, передавая тип пользователя в качестве параметра.

handleLogin = () => {
  const { email, password } = this.state;
  firebase
    .auth()
    .signInWithEmailAndPassword(this.state.email, this.state.password)
    .then(() => {
      // check user type 
      // pass user type as param to home screen
      this.props.navigation.navigate('Home', { userType: 'admin or nomral user' });
    })
    .catch(error => this.setState({ errorMessage: error.message }));
};

В вашем HomeScreen получите тип пользователя, используя const userType = this.props.navigation.getParam('userType', '');

class HomeScreen extends React.Component {
  render = () => {
    const userType = this.props.navigation.getParam('userType', '');
    return (
      <View>
        {typeof userType === 'string' && userType.toLowerCase() === 'admin' ? (
          <Admin />
        ) : (
          <User />
        )}
      </View>
    );
  };
}

DEMO

...