Search code examples
androidreactjsreact-nativereact-native-router-flux

Back button redirects to login screen


I am using react-native-router-flux as my navigator. The issue that I am facing is probably quite simple but I can't seem to put my head into it. When the user logins in to the app, he/she gets redirected to the main dashboard scene. From there, if the user presses the android back button, the app should logically close instead of navigating back to the login screen again but I can't grasp the missing logic for achieving this.

Router:

import React, { Component } from 'react'
import {
  TouchableOpacity
} from 'react-native'
import { Scene, Router, Actions } from 'react-native-router-flux'
import Login from '../pages/login'
import Dashboard from '../pages/dashboard'
import NavigationDrawer from './navigationDrawer'
import Icon from 'react-native-vector-icons/MaterialIcons';

const Menu = () => {
  return(
    <TouchableOpacity
      onPress={ () => Actions.refresh({key: 'drawer', open: value => !value }) }>
      <Icon
        name="view-headline"
        size={30}
        color="white"
      />
    </TouchableOpacity>
  )
}

class NavigationRouter extends Component {

  render() {
    return(
      <Router>
        <Scene initial key="login" component={Login} hideNavBar/>
        <Scene key="drawer" component={NavigationDrawer} open={false} >
          <Scene key="main">
            <Scene initial key="dashboard" title="Dashboard" navigationBarStyle={Styles.navigationBarStyle} component={Dashboard} hideNavBar={false}
              renderLeftButton={() => (<Menu/>)} />
          </Scene>
        </Scene>
      </Router>
    )
  }
}

const Styles = {
  navigationBarStyle: {
    backgroundColor: "#fda21d"
  }
}
export default NavigationRouter;

Dashboard Scene:

import React, {Component} from 'react'
import {
  View,
  Text,
  BackAndroid
} from 'react-native'
import {Actions} from 'react-native-router-flux'
import Icon from 'react-native-vector-icons/MaterialIcons'

class Dashboard extends Component {
  constructor(props) {
    super(props)
    BackAndroid.addEventListener('hardwareBackPress', function() {
      if (this.props.title === 'Dashboard') {
        console.log("pressed");
      }
    })
  }
  render() {
      [...]
  }

I tried using the BackAndroid API that Facebook provided but it is also not working at all.


Solution

  • This is how I did in my app using redux.

    componentWillMount() {
      BackAndroid.addEventListener('hardwareBackPress', this._backAndroid);
    }
    
    componentWillUnMount() {
      BackAndroid.removeEventListener('hardwareBackPress', this._backAndroid);
    }
    
    _backAndroid = () => {
      if (this.props.scene !== "home") {
        try {
          Actions.pop();
          return true;
        } catch(err) {
          return false; // exit app without prompt
        }
      }
    
      Alert.alert(
        'Exit',
        'Are you sure you want to exit?',
        [
          { text: 'Cancel', onPress: () => {} },
          { text: 'Yes', onPress: () => {BackAndroid.exitApp()}},
        ]
      );
      return true;
    }
    

    my reducer

    import { ActionConst } from 'react-native-router-flux';
    
    const initialState = {
      scene: {},
    };
    
    export default function reducer(state = initialState, action = {}) {
      switch (action.type) {
        // focus action is dispatched when a new screen comes into focus
        case ActionConst.FOCUS:
          return {
            ...state,
            scene: action.scene.name,
          };
        default:
          return state;
      }
    }