React Navigation Preventing Back to loading screen, reset doesn't work

I have a React Native app that I have implemented. The application currently opens on a loading screen, which, after installation, tests the function firebase.auth().onAuthStateChanged(...)

.

The app basically decides whether to access the login screen or the home screen depending on whether the user has already been authenticated.

It is implemented as follows:

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 problem.

When I press the Android back button, it goes to the application loading screen, which is clearly not desirable. How can this be prevented?

EDIT:

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

      

+2


source to share


3 answers


Try using a custom navigation component that supports a custom button. Don't forget to add the reducer to the yoru combination reducer 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;
};

      

+1


source



this is my solution :)
I have a StageArea page. it is the bridge between login and timeline. User is not logged in, then go to LoginPage. User is login, then go to Timeline. Click the Back button, then go to the Timeline page again to go to the login page. ("Sori 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;

      

0


source


Enter the code below,

   static navigationOptions = {
       header:null
     };

      

Before as

render() {
     return (

      

on NotesScreen . There will be no back button .

0


source







All Articles