I've finally managed to solve it.
Here's how:
- At the start of my app, when I give an id to my main stack
const sideMenu = {
left: { /*...*/ },
center: {
stack: {
id: 'main', // this line is important
children: [/*...*/]
}
},
};
Navigation.setRoot({
root: { sideMenu },
});
- When I want to start my wizard, I push a new stack
Navigation.push(componentId, {
stack: {
id: 'wizard',
children: [
{
component: { /*...*/ },
},
],
}
})
I push the screens on the new stack wizard
as the user progresses
When I want to display the final summary screen, I call setStackRoot on the nested stack
Navigation.setStackRoot('wizard', [
{
component: { /*...*/ },
},
]);
- On that summary screen, I have a button labelled 'Finish' which removes the nested stack
Navigation.pop('main');
EDIT: with this approach alone, if you click on the back arrow when you are on a nested screen, it will dismiss the entire nested stack instead of this screen only.
I had to use a custom back button as follows:
I solved it by using a custom back button:
1. When pushing a new screen where I want to override the button, use the options
import Icon from 'react-native-vector-icons/MaterialIcons';
/* ... */
const backIcon = await Icon.getImageSource('arrow-back', 24, '#000');
const component = {
id: screenID,
name: screenID,
passProps,
options: {
topBar: {
leftButtons: [
{
id: 'backButton',
icon: backIcon,
},
],
},
}
};
return Navigation.push(componentId, { component });
- Create a HOC to implement you custom back action
import React, { Component } from 'react';
import { Navigation } from 'react-native-navigation';
const getDisplayName = WrappedComponent => WrappedComponent.displayName || WrappedComponent.name || 'Component';
export default function withCustomBackButton(WrappedComponent) {
class WithCustomBackButton extends Component {
componentDidMount() {
this.navigationEventListener = Navigation.events().bindComponent(this);
}
componentWillUnmount() {
if (this.navigationEventListener) this.navigationEventListener.remove();
}
navigationButtonPressed() {
// Your custom action
const { componentId } = this.props;
Navigation.pop(componentId);
}
render() {
return <WrappedComponent {...this.props} />;
}
}
WithCustomBackButton.displayName = `WithCustomBackButton(${getDisplayName(WrappedComponent)})`;
return WithCustomBackButton;
}
- When registering the screen with the custom back button, wrap it in your HOC
import withCustomBackButton from '../components/hoc/WithCustomBackButton';
/* ... */
Navigation.registerComponent('selectLocation', () => withCustomBackButton(SelectLocation));