How to add header bar when using createBottomTabNavigator? - react-native

I'm trying to add a constant Header bar to my screen (all screens, similar to this example) with basic functionality (menu button, and a back button), but I'm having trouble finding a way to do this when using createBottomTabNavigator. I haven't seen anything saying this isn't possible, so if I'm making a design mistake, do let me know.
Here is my minimal foobar example (it runs):
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import { createBottomTabNavigator } from 'react-navigation';
import Ionicons from 'react-native-vector-icons/Ionicons';
class ScreenA extends React.Component {
constructor(props) {
super(props);
this.state = {
screenName: 'Screen A'
}
}
render() {
return (
<View
style={styles.container}
>
<Text>{this.state.screenName}</Text>
</View>
);
}
};
class ScreenB extends React.Component {
constructor(props) {
super(props);
this.state = {
screenName: 'Screen B'
}
}
render() {
return (
<View
style={styles.container}
>
<Text>{this.state.screenName}</Text>
</View>
);
}
};
const BottomTabNav = createBottomTabNavigator(
{
ScreenA: {
screen: ScreenA,
navigationOptions: {
title: '',
tabBarIcon: ({ focused, tintColor }) => {
return <Ionicons
name={ focused ? 'ios-card' : 'ios-card-outline' }
size={30}
style={{ marginTop: 6 }}
/>;
},
}
},
ScreenB: {
screen: ScreenB,
navigationOptions: {
title: '',
tabBarIcon: ({ focused, tintColor }) => {
return <Ionicons
name={ focused ? 'ios-chatbubbles' : 'ios-chatbubbles-outline' }
size={30}
style={{ marginTop: 6 }}
/>;
},
},
}
},
{
initialRouteName: 'ScreenA',
}
);
export default class App extends React.Component {
render() {
return (
<BottomTabNav />
);
}
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
Apologies for not including a Snack link, but I'm having issues with dependencies when trying to build the demo.

You need your screens to be stack navigators which you then can add in your tab navigator. The "defaultNavigationOptions" are your navigationOptions for the header and the navigationOptions in the code snippet corresponds for the BottomTabNavigator options.
You can read more about this here: https://reactnavigation.org/docs/en/navigation-options-resolution.html
const StackA = createStackNavigator({ ScreenA },
{
defaultNavigationOptions: (navigationOptions),
navigationOptions: {
tabBarLabel: 'Screen A',
},
});
const StackB = createStackNavigator({ScreenA},
{
defaultNavigationOptions: (navigationOptions),
navigationOptions: {
tabBarLabel: 'Screen B',
},
});
const tabNavigator = createBottomTabNavigator({StackA, StackB});

only createStackNavigator has its own header so you have to wrap whatever you want in it, according to your question there is two answers to this,
put the createBottomTabNaviagator in a parent createStackNavigator and access the createBottomTabNavigator children routeName and assign it to the parent createStackNavigator header
const BottomTabNav = createBottomTabNavigator({
FirstScreen: ScreenA,
SecondScreen: ScreenB,
});
BottomTabNav.navigationOptions = ({ navigation }) => {
// By default routeName will come from the BottomTabNav,
// but here we can access the children screens
// and give the parent ParentStack that routeName
const { routeName } = navigation.state.routes[navigation.state.index];
// You can do whatever you like here to pick the title based on the route name
const headerTitle = routeName;
return {
headerTitle,
};
};
const ParentStack = createStackNavigator({
Home: BottomTabNav,
AnotherScreen: AnotherScreen,
});
put the child screens in a createStackNavigator so that every child will have its own header
const ScreenA = createStackNavigator({
FirstScreen: ScreenA,
/* other routes here */
});
const ScreenB = createStackNavigator({
SecondScreen: ScreenB,
/* other routes here */
});
const BottomTabNav = createBottomTabNavigator({
FirstScreen: ScreenA,
SecondScreen: ScreenB,
});

Related

react-native Drawer Navigation with Tab Navigation

I'm trying to set a top menu and a tab menu in my app. The bottom tabs are working, but the top menu is not displaying. The top menu that I am trying to set is the one we click and the left menu options show.
class App extends Component {
render() {
const store = createStore(reducers, {}, applyMiddleware(ReduxThunk));
return (
<Provider store={store}>
<AppContainer
ref={navigatorRef => {
NavigationService.setTopLevelNavigator(navigatorRef);
}}
/>
</Provider>
);
}
}
export default App;
class HomeScreen extends React.Component {
render() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Home!</Text>
</View>
);
}
}
class SettingsScreen extends React.Component {
render() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Settings!</Text>
</View>
);
}
}
const TabNavigator = createBottomTabNavigator({
Home: HomeScreen,
Settings: SettingsScreen,
});
const MainStackNavigator = createStackNavigator({
Home: {
screen: TabNavigator
}
});
const AppDrawerNavigator = createDrawerNavigator({
Home:{
screen: MainStackNavigator
}
});
const AppSwitchNavigator = createSwitchNavigator({
Login: { screen: Login },
Main: { screen: AppDrawerNavigator }
});
const AppContainer = createAppContainer(AppSwitchNavigator);
I'm new with react native, so I am not sure the order to set the navigator options. What I'm doing wrong?
Thanks
I've put some code as an example with a MainDrawerNavigator that contains a MainTabNavigator. The tab navigator contains three stack navigators for this purpose I'll only reference the HomeScreenNavigator which is a stack navigator. By default this will show a stack header inside my Home tab but will not show a drawer icon to open the drawer. In order to do this you need to put an icon in to toggle the drawer. I've shown this by accessing the navigationOptions in the HomeScreen specifically shown:
static navigationOptions = (navData) => {
return {
headerLeft: (
<View style={styles.headerButtonLeft}>
<HeaderButtons HeaderButtonComponent={DefaultHeaderButton}>
<Item title="menu" iconName="ios-menu" onPress={() => {
navData.navigation.toggleDrawer()
}} />
</HeaderButtons>
</View>
),
}
}
The above will set an a header button on the left of the HomeScreen and pressing the Item will trigger toggling the drawer open via navData.navigation.toggleDrawer(). Your example would be similar except your outermost navigator would be your switch navigator it seems.
Full code as an example shown below: (let me know if clarification is needed elsewhere).
HomeScreen example:
class HomeScreen extends React.Component {
constructor(props) {
super(props)
this.state = { ... }
}
render() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Home!</Text>
</View>
);
}
static navigationOptions = (navData) => {
return {
headerLeft: (
<View style={styles.headerButtonLeft}>
<HeaderButtons HeaderButtonComponent={DefaultHeaderButton}>
<Item title="menu" iconName="ios-menu" onPress={() => {
navData.navigation.toggleDrawer()
}} />
</HeaderButtons>
</View>
),
}
}
}
HomeScreenNavigator example:
import { createStackNavigator } from 'react-navigation-stack';
import HomeScreen from '../screens/HomeScreen';
import MediaSelectScreen from '../screens/MediaSelectScreen';
import FinalizePostScreen from '../screens/FinalizePostScreen';
import { userInterface } from '../constants/Colors';
import Styles from '../constants/Styles';
const HomeScreenNavigator = createStackNavigator({
Home: HomeScreen,
MediaSelect: MediaSelectScreen,
FinalizePost: FinalizePostScreen
}, {
defaultNavigationOptions: {
headerStyle: {
backgroundColor: userInterface.accentColor,
height: Styles.HEADER_HEIGHT,
},
}
});
export default HomeScreenNavigator;
MainTabNavigator example:
import { createBottomTabNavigator } from 'react-navigation-tabs';
import MessagesScreen from '../screens/MessagesScreen';
import HomeScreenNavigator from './HomeScreenNavigator';
import LearnScreenNavigator from './LearnScreenNavigator';
const MainTabNavigator = createBottomTabNavigator({
LearnScreen: { screen: LearnScreenNavigator, navigationOptions: () => ({
tabBarLabel: 'Learn'
})},
HomeScreen: { screen: HomeScreenNavigator, navigationOptions: {
tabBarLabel: 'Home'
}},
MessagesScreen: { screen: MessagesScreen, navigationOptions: {
tabBarLabel: 'Messages'
}},
});
export default MainTabNavigator;
MainDrawerNavigator example:
import { createDrawerNavigator } from 'react-navigation-drawer';
import { createAppContainer } from 'react-navigation';
import MainTabNavigator from './MainTabNavigator';
const MainDrawerNavigator = createDrawerNavigator({
DrawerNav: MainTabNavigator
}, {
drawerType: 'slide'
});
export default createAppContainer(MainDrawerNavigator);
App.js example:
import React from 'react';
import * as Font from 'expo-font';
import { AppLoading } from 'expo';
import { createStore, combineReducers } from 'redux';
import { Provider } from 'react-redux';
import AppSwitchNavigator from './navigation/AppSwitchNavigator';
export default class App extends React.Component {
state = { ... }
render() {
return (
<Provider store={store}>
<AppSwitchNavigator/>
</Provider>
);
}
}
const store = createStore(rootReducer);
const rootReducer = combineReducers({ ... });

Hide bottom tab naivgation

I have a bottom tab bar that locates in app.js. And I have the class where I want to hide the bottom bar. In page home.js I have 2 classes. 1st one is main (is the list of articles), the second one is for button page navigation (in this class I display articles). How I can hide bottom tab navigation in the second page (where articles are displayed). I have tried tabBarVisible: false, but this does not work. Help me, please.
Code:
// app.js
const TabNavigator = createBottomTabNavigator({
Home:{
screen:Home,
navigationOptions:{
tabBarLabel:'Главная',
tabBarIcon:({tintColor})=>(
<Icon name="ios-home" color={tintColor} size={24} />
)
}
},
Courses:{
screen:Courses,
navigationOptions:{
tabBarLabel:'Courses',
tabBarIcon:({tintColor})=>(
<Icon name="ios-school" color={tintColor} size={24} />
)
}
},
Editor:{
screen:Editor,
navigationOptions:{
tabBarLabel:'Editor',
tabBarIcon:({tintColor})=>(
<Icon name="ios-document" color={tintColor} size={24} />
)
}
},
},{
tabBarOptions:{
activeTintColor:'#db0202',
inactiveTintColor:'grey',
style:{
fontSize:3,
height:45,
backgroundColor:'white',
borderTopWidth:0,
elevation: 5
}
}
});
export default createAppContainer(TabNavigator);
// home.js
import React from 'react';
import { Font } from 'expo';
import { Button, View, Text, SafeAreaView, ActivityIndicator, ListView, StyleSheet, Image, Dimensions,
ScrollView } from 'react-native';
import { createStackNavigator, createAppContainer } from 'react-navigation'; // Version can be specified in package.json
import Icon from 'react-native-vector-icons/Ionicons'
import Courses from './Courses'
class HomeScreen extends React.Component {
static navigationOptions = {
title: 'Home',
};
const { navigate } = this.props.navigation;
return (
<SafeAreaView style={styles.MainContainer}>
<ScrollView
>
<ListView
dataSource={this.state.dataSource}
renderSeparator={this.ListViewItemSeparator}
renderRow={rowData => (
<>
<Text
onPress={() => {
/* 1. Navigate to the Details route with params */
this.props.navigation.navigate("Articles", {
otherParam: rowData.article_title,
});
}}
>
{rowData.article_title}
</Text>
</>
)}
/>
</ScrollView
>
</SafeAreaView>
);
}
}
class ArticleScreen extends React.Component {
static navigationOptions = ({ navigation, navigationOptions }) => {
const { params } = navigation.state;
return {
title: params ? params.otherParam : '',
};
};
render() {
const { params } = this.props.navigation.state;
const article_title = params ? params.otherParam : '';
return (
<Text>{article_title}</Text>
);
}
}
const RootStack = createStackNavigator(
{
Home: {
screen: HomeScreen,
},
Courses: {
screen: Courses,
navigationOptions: {
header: null,
}
},
Articles: {
screen: ArticleScreen,
},
},
{
initialRouteName: 'Home',
}
);
const AppContainer = createAppContainer(RootStack);
export default class App extends React.Component {
render() {
return <AppContainer />;
}
}
const AppContainer = createAppContainer(RootStack);
export default class App extends React.Component {
render() {
return <AppContainer />;
}
}
You have to make StackNavigator as main Navigator and TabBar as a sub navigator:
const TabBar = createBottomTabNavigator(RouteConfigs, TabNavigatorConfig);
const MainNavigator = createStackNavigator(
{
TabBar,
WelcomeScene: { screen:Scenes.WelcomeScene },
HomeScene: { screen: HomeScene }
}
Using this when you go the second screen Tabbar will hide automatically.
Can you try this?
class ArticleScreen extends React.Component {
static navigationOptions = ({ navigation }) => {
return {
title: params ? params.otherParam : '',
tabBarVisible: false
};
};
...
How about something like this. Create Tab navigator and pass it down to Stack navigator as one of the screen, when you navigate to the Articles, it will hide the tab bar...
const TabNavigator = createBottomTabNavigator({
Home: {
screen: Home,
navigationOptions: {
tabBarLabel: 'Главная',
tabBarIcon: ({ tintColor }) => (
<Icon name="ios-home" color={tintColor} size={24} />
),
},
},
Courses: {
screen: Courses,
navigationOptions: {
tabBarLabel: 'Courses',
tabBarIcon: ({ tintColor }) => (
<Icon name="ios-school" color={tintColor} size={24} />
),
},
},
Editor: {
screen: Editor,
navigationOptions: {
tabBarLabel: 'Editor',
tabBarIcon: ({ tintColor }) => (
<Icon name="ios-document" color={tintColor} size={24} />
),
},
},
}, {
tabBarOptions: {
activeTintColor: '#db0202',
inactiveTintColor: 'grey',
style: {
fontSize: 3,
height: 45,
backgroundColor: 'white',
borderTopWidth: 0,
elevation: 5,
},
},
});
const stackNavigator = createStackNavigator({
Home: {
screen: TabNavigator,
navigationOptions: {
header: null,
},
},
Articles: {
screen: ArticleScreen,
},
// add screens here which you want to hide the tab bar
});
export default createAppContainer(stackNavigator);

Dynamically change header title in react native navigation

For a school assignment we're creating an app in react native with react navigation and redux. Because all of us are new to react we have an issue we are unable to resolve.
We want to change the title of the header when a certain button is clicked. The first time we click a button it changes the header title just fine. The problem arrises when we press a different button, the header doesn't change. Note that no matter what option we choose, we always go to the same screen.
import React from 'react';
import { createStackNavigator, createAppContainer, createDrawerNavigator } from 'react-navigation';
import {connect} from 'react-redux';
import { store } from '#redux/MyStore';
import { Ionicons } from '#expo/vector-icons';
import ScannerScreen from '#screens/ContactScreen';
import EventsScreen from '#screens/ListScreen';
const ContactStack = createStackNavigator({
Contact: {
screen: ContactScreen,
navigationOptions: ({navigation}) => ({
headerStyle: {backgroundColor: '#fa8231'},
headerTitleStyle: {fontSize: 18},
title: store.getState().setupState.title,
headerLeft: <Ionicons
name="md-menu" style={{marginLeft:10}}
size={28}
onPress={() => navigation.toggleDrawer()} /> //menu button
})
}
});
// Code to create stack for the ListStack
const DrawerStack = createDrawerNavigator({
Contact: ContactStack,
List: ListStack
});
const PrimaryNavigation = createStackNavigator({
ListStack: {
screen: ListStack,
navigationOptions: {
header: null,
},
},
DrawerStack: {
screen: DrawerStack,
navigationOptions: {
header: null,
},
},
},
{
initialRouteName: 'ListStack',
});
const AppContainer = createAppContainer(PrimaryNavigation);
class AppNavigation extends React.Component {
render() {
return <AppContainer/>
}
}
export default (AppNavigation)
We did get it working when we put the title bar in the DrawerNavigator, but since we want the Drawer in from of the header that is not an option. My speculation is that the stack is created once with a certain title and never gets updated when switching screens using the DrawerNavigator but we have no clue how to fix that.
Thanks in advance!
From what I understand you need to change the title when a screen is loaded in stack.So you could use some like:
class ScreenInContactStack extends React.Component{
//Constryctor
static navigationOptions = ({navigation}) => ({
title: (navigation.state.params || {}).title || 'Chat! ',
});
//Remaining Logic
}
and while calling
this.props.navigation.navigate('ScreenInContactStack', {title: yourTitle + ' ',});
Don't know why but the Appbar condense the title to like yourTi.. to avoid this add a space to the title.
Try this:
map title as a prop to force ContactStack to re-render whenever it changes
class ContactStack extends React.Component {
render() {
const { title } = this.props.setupState;
const Stack = createStackNavigator({
Contact: {
screen: ContactScreen,
navigationOptions: ({navigation}) => ({
headerStyle: {backgroundColor: '#fa8231'},
headerTitleStyle: {fontSize: 18},
title,
headerLeft: <Ionicons
name="md-menu" style={{marginLeft:10}}
size={28}
onPress={() => navigation.toggleDrawer()} /> //menu button
})
}
});
return <Stack />;
}
}
const mapStateToProps = ({ setupState }) => ({setupState});
export default connect(mapStateToProps)(ContactStack);

How to export Appcontainer and Import in another Screenpage?

my main app is about bottom tab navigator.on that i have using 5 screens.
one screen from the 5 screen i need to use createstacknavigator and i need to export that appcontainer class and import in main screen its not exporting that class saying undefined is not a function(evaluating,(0,b.createAppcontainer)(D)')enter code here
./createStacknavigator
import React from 'react';
import { View, Text, Button } from 'react-native';
import { createAppContainer, createStackNavigator, StackActions, NavigationActions } from 'react-navigation'; // Version can be specified in package.json
class HomeScreen extends React.Component {
render() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
<Button
title="Go to Details"
onPress={() => {
this.props.navigation.dispatch(StackActions.reset({
index: 0,
actions: [
NavigationActions.navigate({ routeName: 'Details' })
],
}))
}}
/>
</View>
);
}
}
class DetailsScreen extends React.Component {
render() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Details Screen</Text>
</View>
);
}
}
const AppNavigator = createStackNavigator({
Home: {
screen: HomeScreen,
},
Details: {
screen: DetailsScreen,
},
}, {
initialRouteName: 'Home',
});
export default createAppContainer(AppNavigator);
In MainScreen Page
./Mainscreen
...
import AppNavigator from './components/createStacknavigator.js';
My error is:
undefined is not a function(evaluating,(0,b.createAppcontainer)(D)')
You can use createAppContainer like below:
import React from 'react';
import {
createBottomTabNavigator,
createStackNavigator,
createSwitchNavigator,
createAppContainer
} from 'react-navigation';
const onTabTap = (n) => {
ReactNativeHapticFeedback.trigger('selection', false);
n.defaultHandler();
};
const TabNavigator = createBottomTabNavigator({
Home: {
screen: Jobs,
navigationOptions: () => ({
tabBarOnPress: onTabTap
})
},
Calendar: {
screen: Calendar,
navigationOptions: () => ({
tabBarOnPress: onTabTap
})
}
},
{
defaultNavigationOptions: ({ navigation }) => ({
tabBarIcon: ({ focused }) => {
const { routeName } = navigation.state;
let IconComponent = CONST.IC_HOME;
if (routeName === CONST.MENU_HOME) {
IconComponent = focused ? CONST.IC_HOME_SELECTED : CONST.IC_HOME;
} else if (routeName === CONST.MENU_CALENDAR) {
IconComponent = focused ? CONST.IC_CALENDAR_SELECTED : CONST.IC_CALENDAR;
}
return IconComponent;
}
}),
tabBarOptions: {
activeTintColor: 'red',
inactiveTintColor: 'black',
},
});
const DashBoardStack = createStackNavigator({
DashBoard: TabNavigator
}, {
mode: 'modal',
headerMode: 'none',
});
const App = createSwitchNavigator({
App: DashBoardStack
},
{
initialRouteName: 'App'
});
const AppContainer = createAppContainer(App);
class App extends React.Component {
render() {
return (
<React.Fragment>
<AppContainer />
</React.Fragment>
);
}
}
export default App;

How to pass a prop to all tabs of a createBottomTabNavigator

My application is calling a createBottomTabNavigator from a createSwitchNavigator using the following this.props.navigation.navigate('AppMenu', {UserName: 'First Name'}); The createBottomTabNavigator consists of 2 tabs, one is a Stack Navigator and the second is just a React component. When I navigate to the initialRouteName of the Stack Navigator the prop I passed in is available, but if I select the second tab of the Tab Navigator the prop is not available.
Is there a way I can pass a prop to all tabs of a Bottom Tab Navigator when it is rendered?
Here is a diagram of the applications, and sample code that can be run in Snack.
import React from 'react';
import { Text, View, Button } from 'react-native';
import { createBottomTabNavigator, createStackNavigator, createSwitchNavigator } from 'react-navigation';
class LoginScreen extends React.Component {
_navToMain = () => {
console.log('Login Screen: Passing user: First Name');
this.props.navigation.navigate('AppMenu', {UserName: 'First Name'});
}
render () {
return (
<View style={{flexDirection: 'column', paddingTop:20}}>
<Text>Pass UserName prop to createBottomTabNavigator</Text>
<Button title='Login!' onPress={this._navToMain}/>
</View>
)
}
}
class SyncScreen extends React.Component {
static navigationOptions = ({ navigation }) => {
return {
headerTitle: 'Sync Screen',
};
};
render () {
return (
<View style={{flexDirection: 'column', paddingTop:20}}>
<Text>Sync Screen Navigation Prop UserName (missing!): {JSON.stringify(this.props.navigation.getParam('UserName'))}</Text>
<Button title='Test Button' onPress={() => {}} />
</View>
);
}
}
class AppMenuScreen extends React.Component {
static navigationOptions = ({ navigation }) => {
return {
headerTitle: 'Stack Navigator',
};
};
_navToOne = () => {
console.log('Going to Stack One')
this.props.navigation.navigate('StackOne', {UserName: this.props.navigation.getParam('UserName')});
}
render () {
return (
<View style={{flexDirection: 'column'}} >
<Text>App Menu Navigation Prop UserName passed from SwitchNavigator: {JSON.stringify(this.props.navigation.getParam('UserName'))}</Text>
<Button title='Screen one' onPress={this._navToOne} />
</View>
)
}
}
class StackOneScreen extends React.Component {
static navigationOptions = ({ navigation }) => {
return {
headerTitle: 'Stack One Screen',
};
};
render () {
return (
<View style={{flexDirection: 'row'}} >
<Text>Stack One Screen Navigation Props: {JSON.stringify(this.props.navigation.getParam('UserName'))}</Text>
</View>
)
}
}
const AppStack = createStackNavigator(
{
AppMenu: AppMenuScreen,
StackOne: StackOneScreen,
},
{
initialRouteName: "AppMenu",
navigationOptions: {
headerTintColor: "#a41034",
headerStyle: {
backgroundColor: "#fff"
}
}
}
);
const MainTabs = createBottomTabNavigator(
{
'Apps': { screen: AppStack },
'Sync': { screen: SyncScreen },
},
{
navigationOptions: ({ navigation }) => ({
title: navigation.state,
tabBarIcon: ({ focused, horizontal, tintColor }) => {
const { routeName } = navigation.state;
}
}),
tabBarOptions: {
activeTintColor: 'red',
inactiveTintColor: 'gray',
tabBackgroundColor: 'black',
labelStyle:{
fontSize: 24,
marginBottom:10,
}
},
animationEnabled: true,
swipeEnabled: false,
}
);
const AppNavigator = createSwitchNavigator(
{
Login: LoginScreen,
Main: MainTabs
},
{
initialRouteName: 'Login',
backBehavior: "initialRoute",
}
);
export default class App extends React.Component {
render() {
return (
<AppNavigator />
);
}
}
Package.json
"react": "16.5.0",
"react-native": "0.57.1",
"react-navigation": "^2.0.0"
you can pass props on navigate using
_navToOne = () => {
console.log("Going to Stack One");
this.props.navigation.navigate({
routeName: "StackOne",
params: { UserName: this.props.navigation.state.params.UserName }
});
};
if you want to access props passed using navigate
this.props.navigation.state.params.PROPNAME
// PROPNAME is the prop you passed and want to get
It's just a temporary solution, at least these code can solve your issue
When I navigate to the initialRouteName of the Stack Navigator the prop I passed in is available, but if I select the second tab of the Tab Navigator the prop is not available
because you just sent the param into AppMenu using this.props.navigation.navigate('AppMenu', {UserName: 'First Name'});
UserName is available on both of tab after i change the code of LoginScreen class :
class LoginScreen extends React.Component {
_navToMain = () => {
console.log('Login Screen: Passing user: First Name');
//-------add this-------
this.props.navigation.navigate('Sync', {UserName: 'First Name'});
//----------------------
this.props.navigation.navigate('AppMenu', {UserName: 'First Name'});
}
render () {
return (
<View style={{flexDirection: 'column', paddingTop:20}}>
<Text>Pass UserName prop to createBottomTabNavigator</Text>
<Button title='Login!' onPress={this._navToMain}/>
</View>
)
}
}