React Navigation Preventing返回加载屏幕,重置不起作用

时间:2017-08-08 18:20:09

标签: firebase react-native firebase-authentication react-native-android react-navigation

我已经实现了一个React Native应用程序。目前,该应用程序在加载屏幕上打开,加载屏幕在安装后检查firebase.auth().onAuthStateChanged(...)功能。

应用程序基本上决定是否进入登录屏幕或主屏幕,具体取决于用户是否已经过身份验证。

它是这样实现的:

主导航:

const MainNavigator = TabNavigator({
  auth: {
    screen: TabNavigator({
      login: { screen: LoginScreen },
      signup: { screen: SignupScreen }
    }, {
      initialRouteName: 'login',
      tabBarPosition: 'top',
      lazy: true,
      animationEnabled: true,
      swipeEnabled: true,
      tabBarOptions: {
        labelStyle: { fontSize: 12 },
        showIcon: true,
        iconStyle: { width: 30, height: 30 } 
      }
    })
  },
  main: {
    screen: StackNavigator({
      notes: { screen: NotesScreen }
    }, {
      initialRouteName: 'notes'
    })
  },
  loading: { screen: LoadingScreen }
}, {
  initialRouteName: 'loading',
  lazy: true,
  swipeEnabled: false,
  animationEnabled: false,
  navigationOptions: {
    tabBarVisible: false
  }
});

载入画面:

class LoadingScreen extends Component {
  componentDidMount() {
    const { navigate } = this.props.navigation;

    firebase.auth().onAuthStateChanged(user => {
      if (user) {
        navigate('main');
      } else {
        navigate('auth');
      }
    });
  }

  render() {
    return (
      <View style={styles.spinnerStyle}>
        <Spinner size="large" />
      </View>
    );
  }
}

const styles = {
  spinnerStyle: {
    flexDirection: 'row',
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center'
  }
};

除了一个问题之外,这很有效。

当我按下Android的硬件返回按钮时,它会转到应用程序加载屏幕,这显然是不受欢迎的。我该如何预防?

修改

我已经尝试了以下操作,它也没有工作:

const resetAction = (routeName) => NavigationActions.reset({
  index: 0,
  actions: [NavigationActions.navigate({ routeName })],
  key: null
});

class LoadingScreen extends Component {
  componentDidMount() {
    const { dispatch } = this.props.navigation;

    firebase.auth().onAuthStateChanged(user => {
      if (user) {
        this.props.setUser(user);
        dispatch(resetAction('main'));
      } else {
        dispatch(resetAction('auth'));
      }
    });
  }

  render() {
    return (
      <View style={styles.spinnerStyle}>
        <Spinner size="large" />
      </View>
    );
  }
}

4 个答案:

答案 0 :(得分:1)

尝试使用自定义后退按钮支持的自定义导航组件。别忘了将reducer添加到yoru combine reducers函数中。

创建导航组件:

import React, { Component } from 'react';
import { BackHandler } from 'react-native';
import { connect } from 'react-redux';
import { addNavigationHelpers } from 'react-navigation';
import MainNavigator from './MainNavigator';

class AppWithNavigationState extends Component {
  componentDidMount () {
    BackHandler.addEventListener('hardwareBackPress', () => {
      this.props.dispatch({
        type: 'Navigation/BACK'
      });

      return true;
    });
  }

  componentWillUnmount () {
    BackHandler.removeEventListener('hardwareBackPress');
  }

  render () {
    return (
      <MainNavigator navigation={addNavigationHelpers({
        dispatch: this.props.dispatch,
        state: this.props.nav
      })}/>
    );
  }
}

export default connect((state) => ({ nav: state.nav }))(AppWithNavigationState);

创建导航缩减器:

import { NavigationActions } from 'react-navigation';
import MainNavigator from './MainNavigator';
import { NAVIGATION_ON_SIGN_IN } from '../redux/actions/ActionTypes';
import { BackHandler } from 'react-native';

const initialState = MainNavigator.router.getStateForAction(MainNavigator.router.getActionForPathAndParams('loading'));

function appShouldClose (nextState) {
  const { index, routes } = nextState;

  return index === 0 || routes[1].routeName === 'auth';
}

export default (state = initialState, action) => {
  const { router } = MainNavigator;
  let nextState;

  switch (action.type) {
    case NavigationActions.BACK:
      nextState = router.getStateForAction(action, state);
      appShouldClose(nextState) && BackHandler.exitApp();
      break;

    default:
      nextState = router.getStateForAction(action, state);
  }

  return nextState || state;
};

答案 1 :(得分:1)

使用切换导航器,直到用户成功登录(加载和登录页面),然后再使用堆栈导航器(用户主页和随后的其他页面)。

switchNavigator(loading, login, stackNavigator)

stackNavigator(user homepage,....)

答案 2 :(得分:0)


这是我的解决办法:) 我有StageArea页面。它是从登录到时间线之间的桥梁。用户没有登录然后转到LoginPage。用户登录然后转到时间轴。用户按下后退按钮然后再次进入TimeLine页面而不进入登录页面。(Sory for my english)

import React, { Component } from 'react';
import { View  } from 'react-native';
import LoginForm from './LoginForm';
import Timeline from './Timeline';
import firebase from 'firebase';
import InitialPage from './InitialPage'
class StageArea extends  Component {


    state = {isLoggin:''};

    componentWillMount(){
        firebase.auth().onAuthStateChanged((user) => {
            if (user) {
                    this.setState({ isLoggin:true})
            }else {
                this.setState({ isLoggin:false})

            }
        })

    }

    render() {
        if(this.state.isLoggin)
        {
            return(<Timeline/>);

        }
        else if (this.state.isLoggin===false) {
            return(<LoginForm/>);
        }

    }
}

export default StageArea;

答案 3 :(得分:-1)

写下面的代码,

   static navigationOptions = {
       header:null
     };

就在

之前
render() {
     return (
NotesScreen 上的

,没有任何后退按钮