2

I am following the docs trying to handle the Android back button when using react navigation integrated with redux.

Currently pressing the back button exits the entire app wherever you press it. I have tried to handle back press following the guides by adding the handler on the Root component:

 const persistConfig = {
      key: 'root',
      storage,
      blacklist: ['nav'],
    };

    const AppNavigator = createStackNavigator(
      {
        SelectScreen,
        PageScreen,
        SettingsScreen,
      },
      {
        initialRouteName: 'SelectScreen',
      },
    );

    const navReducer = createNavigationReducer(AppNavigator);
    const appReducer = combineReducers({
      nav: navReducer,
      theme: themeReducer,
      page: pageReducer,
    });
    const persistedReducer = persistReducer(persistConfig, appReducer);

    const middleware = createReactNavigationReduxMiddleware('root', state => state.nav);

    const App = reduxifyNavigator(AppNavigator, 'root');
    const mapStateToProps = state => ({
      state: state.nav,
    });
    const AppWithNavigationState = connect(mapStateToProps)(App);

    const store = createStore(persistedReducer, applyMiddleware(middleware));
    const persistor = persistStore(store);

    class Root extends React.Component {

componentDidMount() {
    BackHandler.addEventListener("hardwareBackPress", this.onBackPress);
  }

  componentWillUnmount() {
    BackHandler.removeEventListener("hardwareBackPress", this.onBackPress);
  }

  onBackPress = () => {
    const { dispatch, nav } = this.props;
    if (nav.index === 0) {
      return false;
    }

    dispatch(NavigationActions.back());
    return true;
  };
      render() {
        return (
          <Provider store={store}>
            <PersistGate loading={null} persistor={persistor}>
              <AppWithNavigationState />
            </PersistGate>
          </Provider>
        );
      }
    }

    AppRegistry.registerComponent(appName, () => Root);

However, I am getting an error because the navigation props doesn't exist in the root component. I know this is probably an error due to my lack of understanding so I'd really appreciate some help on how to get this working!

Thanks

2 Answers 2

0

You can do it by passing it to another component which has access to the Provider store.

AppNavigation.js

const PrimaryNav = createStackNavigator(
      {
        SelectScreen,
        PageScreen,
        SettingsScreen,
      },
      {
        initialRouteName: 'SelectScreen',
      },
 );

export const appNavigatorMiddleware = createReactNavigationReduxMiddleware(
  'root',
  state => state.nav
); //... Import it to your configure store file, to apply the middleware

const AppNavigator = reduxifyNavigator(PrimaryNav, 'root');

export default AppNavigator

ReduxNavigation.js

import React from 'react'
import { BackHandler, Platform } from 'react-native'
import { connect } from 'react-redux'
import AppNavigation from './AppNavigation' //... Import from AppNavigation.js

class ReduxNavigation extends React.Component {
  ...// Add your BackHandler Code here

  render () {
    return <AppNavigation state={this.props.nav}  dispatch={this.props.dispatch}/>
  }
}

const mapStateToProps = state => ({ nav: state.nav })
export default connect(mapStateToProps)(ReduxNavigation)

App.js

class App extends Component {
  render () {
    return (
      <Provider store={store}>
        <PersistGate loading={null} persistor={persistor}>
         <RootContainer />
        </PersistGate>
      </Provider>
    )
  }
}
Sign up to request clarification or add additional context in comments.

1 Comment

appNavigatorMiddleware should be imported where you'll create and initialize the store in the applyMiddleware, RootContainer.js is just another component, which you need to add to App.js
0

As I haven't got enough rep I have to post this as an answer.

Have a read through this:

https://reactnavigation.org/docs/en/custom-android-back-button-handling.html

Have a look through the example but look at the listener in the constructor:

this._didFocusSubscription = props.navigation.addListener('didFocus', payload =>
  BackHandler.addEventListener('hardwareBackPress', this.onBackButtonPressAndroid)
);

Looks like you're on the right track, you just need to add the listener to the props.navigation

2 Comments

Thanks for the answer! I've tried that but I get an error, props.navigation is undefined. Still the same issue I initially had, there is no navigation prop in this component
What versions of React Native and Navigation are you using?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.