I will be updating this guide frequently as I am currently the migrating a project from ex-navigation to react-navigation. Please let me know if there are any mistakes or if it could be done in a better way.
Hope this guide helps everyone who ever is planning to migrate or is currently migrating to react-navigation.
react-navigation: 1.5.2 and react-native: 0.45.1
- ex-navigation:
<StackNavigation
defaultRouteConfig={{
navigationBar: {
// hiding navigation bar for the entire stack
visible: false,
},
}}
initialRoute="root"
/>
- react-navigation:
const RootStack = StackNavigator({
settings: {
screen: Settings,
navigationOptions: {
header: null,
},
},
contacts: {
screen: Contacts,
}
}, {
initialRouteName: 'root',
// hiding navigation bar in the entire stack
});
- There is no NavigationProvider in react-navigation.
- Declaring a stack in ex-navigation:
return (
<NavigationProvider router={Router}>
<StackNavigation
id="root"
defaultRouteConfig={{
navigationBar: {
visible: true,
height: navBarHeight,
elevation: 0,
tintColor: SColor.orange,
renderTitle: () => <HeaderLogo />,
renderRight: (route, props) => <ProfilePicture {...props} route={route} />,
},
}}
initialRoute="home"
/>
</NavigationProvider>
);
- Declaring a stack in react-navigation:
const RootStack = StackNavigator({
root: {
screen: HomeContainer,
navigationOptions: {
headerTitle: () => <HeaderLogo />,
headerRight: <BlogProfilePicture />,
headerStyle: {
backgroundColor: '#ffffff',
borderBottomColor: '#ffffff',
},
},
},
}, {
mode: 'modal',
initialRouteName: 'root',
headerMode: 'none',
});
export default RootStack;
// or if you want to add some logic around your stack
// you can also export it from a stateless/stateful component
export default class RootContainer extends React.Component {
render() {
return <RootStack />;
}
}
We would normally need to pass navigation prop to a nested stack in-order to close the child stack and return to parent stack:
- react-navigation
const ProfileStack = StackNavigator({
profileSettings: {
screen: ProfileSettings,
},
personalSettings: {
screen: PersonalSettings,
}
});
const SettingStack = TabNavigator({
profile: {
screen: ProfileStack,
navigationOptions: ({ navigation }) => {
headerRight: <ExitButton navigation={navigation} />,
}
}
});
const RootStack = StackNavigator({
Home: {
screen: HomeContainer,
},
Settings: {
screen: SettingsStack,
}
}, {
headerMode: 'modal'
});
- ex-navigation
// passing params `name: foo`
this.props.navigator.push('home', { name: 'foo' });
// accessing name param
this.props.route.params.name;
- react-navigation
// passing params `name: foo`
this.props.navigation.navigate('home', { name: 'foo' });
// accessing name param
this.props.navigation.state.params.name;
- ex-navigation
<StackNavigation
id="profile"
defaultRouteConfig={{
navigationBar: {
visible: true,
tintColor: 'red',
height: navBarHeight,
renderTitle: () => <HeaderLogo />,
elevation: 0,
renderRight: (route, props) => <ProfileSwitcher route={route} {...props} />,
},
}}
initialRoute={'profile'}
/>
- react-navigation
const HomeContainer = (props) => {
const { email, flow } = props.navigation.state.params;
let routeName = 'home';
if ((flow === 'loggedOut')) {
routeName = 'login';
}
const Stack = StackNavigator({
home: {
screen: Home,
},
login: {
screen: Login,
},
}, {
initialRouteName: routeName,
initialRouteParams: { flow },
});
return <Stack />;
};
In react-navigation header consists of 3 parts:
- headerLeft (allows us to specify custom component)
- headerTitle (the centre portion of the navbar)
- headerRight (can be used to add a profile switcher or any other button if needed)
- Adding header logo/title in centre:
// react navigation
const CustomBackButton = (props) => {
return (
<TouchableHighlight onPress={props.onPress}>
<View>
<Text>Back</Text>
</View>
</TouchableHighlight>
);
}
const Stack = StackNavigator({
home: {
screen: Home,
navigationOptions: ({ navigation }) => ({
headerTitle: <Header />,
// this just changes the back button icon and keeps the default back
// button behaviour
headerLeft: <CustomBackButton onPress={navigation.goBack} />,
// you can pass navigation to headerRight also and navigate to a particular
// screen on clicking it like to a profile page
headerRight: <ProfileIcon />,
headerStyle: {
backgroundColor: '#ffffff', // backgroundColor color of entire header section
borderBottomColor: '#ffffff', // border bottom color of entire header
// if you have multiple headers where the top layer might have a logo and second level might
// have a tab navigator, one would want both the headers to appear as a single header
// so, elevation 0 hides the shadow effect/elevation in android
elevation: 0,
},
},
},
login: {
screen: Login,
},
}, {
initialRouteName: routeName,
initialRouteParams: { flow },
});
- hiding back button alone on a particular screen:
In iOS the headerTitle
appears in centre but in Android the header moves towards the left if there is no navigation history (as the header layout is aligned towards left). So in some cases we would want the headerLeft
to just occupy left portion, just to make the headerTitle
centred.
const PlaceholderButton = () => {
return (
<View style={{ backgroundColor: '#fff' }} />
);
};
const Stack = StackNavigator({
home: {
screen: Home,
navigationOptions: {
headerTitle: <Header />,
headerLeft: <PlaceholderButton />,
headerRight: <ProfileIcon />,
}
},
});