反应导航防止返回到加载屏幕,重置不工作 [英] React Navigation Preventing Going back to loading screen, reset not working

查看:783
本文介绍了反应导航防止返回到加载屏幕,重置不工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



该应用程序基本上决定是否到达登录屏幕或主屏幕取决于用户是否已经过身份验证。



它是这样实现的:

Main Navigator:

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

载入画面:

 类LoadingScreen扩展组件{
componentDidMount(){
const {navigate} = this.props.navigation;

firebase.auth()。onAuthStateChanged(user => {
if(user){
navigate('main');
} else {
navigate('auth');
}
}); (
< View style = {styles.spinnerStyle}>
< Spinner size =large(


) />
< / View>
);


$ b const style = {
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扩展组件{
componentDidMount(){
const {dispatch} = this.props.navigation;

firebase.auth()。onAuthStateChanged(user => {
if(user){
this.props.setUser(user);
dispatch(resetAction ('main'));
} else {
dispatch(resetAction('auth'));
}
}); (
< View style = {styles.spinnerStyle}>
< Spinner size =large(


) />
< / View>
);



解决方案

具有自定义后退按钮支持的自定义导航组件。不要忘记将reducer添加到yoru combine redurs函数中。
$ b

创建导航组件:

 从'react'导入React,{Component}; 
从'react-native'导入{BackHandler};
从'react-redux'导入{connect};
从'react-navigation'导入{addNavigationHelpers};
从'./MainNavigator'导入MainNavigator;
$ b $ class AppWithNavigationState extends Component {
componentDidMount(){
BackHandler.addEventListener('hardwareBackPress',()=> {
this.props.dispatch({
type:'Navigation / BACK'
});

return true;
});


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


$(b
$)返回(
dispatch:this.props.dispatch,
state:this.props.nav
})} />
); ((state)=>({nav:state.nav}))(AppWithNavigationState);



export default

创建导航缩减器:

 从'react-navigation'导入{NavigationActions}; 
从'./MainNavigator'导入MainNavigator;
从'../redux/actions/ActionTypes'导入{NAVIGATION_ON_SIGN_IN};
从'react-native'导入{BackHandler};
$ b $ const initialState = MainNavigator.router.getStateForAction(MainNavigator.router.getActionForPathAndParams('loading'));

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

返回索引=== 0 ||路由[1] .routeName ==='auth';
}

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

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

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

返回nextState ||州;
};


I have a React Native application which I have implemented. Currently the app opens up on a loading screen which after mounting checks the firebase.auth().onAuthStateChanged(...) feature.

The app basically decides whether or not to got to the login screen or to main screen depending on whether or not the user is already authenticated.

It is implemented like this:

Main Navigator:

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
  }
});

Loading Screen:

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'
  }
};

This works well except for one issue.

When I press the hardware back button for Android, it goes to the application loading screen which obvious is undesired. How do I prevent that?

EDIT:

I've tried the following and it didn't work either:

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>
    );
  }
}

解决方案

Try a custom navigation component with custom back button support. Dont forget to add the reducer to yoru combine reducers function.

Create a navigation component:

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);

Create a navigation reducer:

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;
};

这篇关于反应导航防止返回到加载屏幕,重置不工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆