Как Перенаправить на Вход, если страница защищена, а пользователь не вошел в систему? - PullRequest
0 голосов
/ 25 апреля 2019

В моем приложении есть несколько общедоступных экранов, которые доступны, даже если пользователь не вошел в систему, и некоторые экраны защищены (вы должны войти в систему, чтобы получить к ним доступ).

Мое решение проблемыэто проверка компонента willFocus Listener, и если пользователь не вошел в систему, пользователь должен быть перенаправлен на loginPage.

export async function ProtectRoute(navigation){

//if page will enter and the user is not authenticated return to login
navigation.addListener(
    'willFocus',
    async () => {
        let token = await getTokenAsync();

        if(!token){
            navigation.navigate('Login');
        }
    })
}

На моем экране я вызываю эту функцию в жизненном цикле ComponentWillMount.Проблема в том, что проверка токена занимает всего секунду, и страница отображается на короткое время.

Как я могу сделать так, чтобы он шел без промедления прямо на страницу входа?

Ответы [ 2 ]

0 голосов
/ 25 апреля 2019

Проблема в том, что проверка токена занимает всего секунду, и страница отображается на короткое время.

Причина в том, что чтение / запись из / в AsyncStorage является асинхронной операцией.

На моем экране я вызываю эту функцию в жизненном цикле ComponentWillMount.

Я предлагаю вам не использовать ComponentWillMount жизненный цикл, поскольку он устарел и будет удален из React (https://reactjs.org/docs/react-component.html#unsafe_componentwillmount)

После этого вступления я покажу вам, как я этого добился в своем приложении: API КОНТЕКСТА! (https://reactjs.org/docs/context.html)

Контекст обеспечивает способ передачи данных через дерево компонентов без необходимости вручную передавать реквизиты на каждом уровне.

Как реализовать контекстный API: контекст будет «состоянием» вашего файла App.js. Ваш root.js будет провайдером контекста, в то время как другие представления, которым потребуется контекст, называются потребителей контекста.

  1. Прежде всего, вам нужно создать «скелет» вашего контекста в отдельный файл, что-то вроде этого:
// AuthContext.js
import React from 'react'
const AuthContext = React.createContext({
  isLogged: false,
  login: () => {},
  logout: () => {}
})
export default AuthContext
  1. Ваш App.js импортирует, содержит и инициализирует контекст:
// App.js
// all necessary imports
import AuthContext from '....'
export default class App extends React.Component {
  constructor (props) {
    super(props)
    this.state = {
      isAuth: false,
      login: this.login,
      logout: this.logout
    }

    login = async userData => {
    // do your login stuff and then
    this.setState({ isAuth: true })
    }

    logout = async () => {
    // do your logout stuff and then
    this.setState({ isAuth: false })
    }

    async ComponentDidMount () {
      // check the asyncStorage here and then, if logged:
      this.setState({ isAuth: true })
    }

    render () {
      return (
        <AuthContext.Provider value={this.state}>
          <AppContainer />
        </AuthContext.Provider>
      )
    }
  1. Затем в представлении, содержащемся в AppContainer, вы можете получить доступ к контексту следующим образом:
import AuthContext from '.....'
// all necessary imports
export default class YourView extends React.Component<Props, State> {
  constructor (props) {
    super(props)
    this.props = props
    this.state = { ... }
  }

  // THIS IS IMPORTANT
  static contextType = AuthContext
  // with this, you can access the context through 'this.context'

  ComponentDidMount () {
    if (!this.context.isAuth) this.props.navigation.navigate('login')
  }

Преимущества этого подхода:

  1. Проверка логического значения выполняется так быстро, что вы не увидите пустой экран.
  2. Общий доступ к контексту аутентификации в вашем приложении
  3. Предоставление доступа к asyncstorage только при первом монтировании приложения, а не каждый раз, когда вам нужно проверять, вошел ли пользователь в систему
  4. Совместное использование методов входа / выхода из любого места в вашем приложении
0 голосов
/ 25 апреля 2019

Я написал быстрый пример ниже.Вы можете изучить и использовать его.

import React, { Component } from "react";
import { Text, View } from "react-native";

const withAuth = WrappedComponent => {
  class AuthenticationScreen extends Component {
    constructor(props) {
      super(props);

      this.state = {
        isAuthenticated: false
      };

      props.navigation.addListener("willFocus", async () => {
        await this.checkAuth();
      });
    }

    remoteReuqest = async () => {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve(true);
        }, 2000);
      });
    };

    checkAuth = async () => {
      const result = await this.remoteReuqest();
      if (result) {
        this.setState({
          isAuthenticated: true
        });
      } else {
        this.props.navigation.navigate("Login");
      }
    };

    render() {
      if (!this.state.isAuthenticated) {
        return <Text>Waiting...</Text>;
      }
      return <WrappedComponent {...this.props} />;
    }
  }

  return AuthenticationScreen;
};

export default withAuth;

Вы можете использовать его следующим образом.

import React, { Component } from "react";
import { Text, StyleSheet, View } from "react-native";
import withAuth from "./withAuth";

class ContactScreen extends Component {
  render() {
    return (
      <View>
        <Text> Contact Screen </Text>
      </View>
    );
  }
}

const styles = StyleSheet.create({});

const extendedComponent = withAuth(ContactScreen);

extendedComponent.navigationOptions = {
  title: "Contact"
};
export default extendedComponent;

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...