I am working with react native for 3 months now and i have this problem now for several days without any solution.
The Problem:
I have a nested TabNavigator inside a StackNavigator. Both of these navigators are inside a stateless component:
const MyStackNav = StackNavigator({
Tabs:{
screen: TabNavigator({
Tab1: { screen: TabScreen1},
Tab2: { screen: TabScreen2},
Tab3: { screen: TabScreen3},
...(CONDITION ? { Tab4: {
screen: TabScreen4
}} : {})
})
}
StackScreen1:{
screen: StackScreenOne,
},
StackScreen2:{
screen: StackScreenTwo,
},
})
Calling of the component:
class MainApp extends React.Component {
constructor(props)
{
super(props);
this.state = {
condition: false,
};
}
render() {
return (
<MyStackNav/>
);
}
}
How can I pass the condition from my class MainApp to the condition variable inside the MyNavStack component for the conditional rendering?
So Tab4 should only be rendered if CONDITION is true.
And the second question would be:
How can I pass a prop from my class MainApp to, for example, the first tab screen?
Thanks in advance!
You can give you MyStackNav a property like: <MyStackNav condition={this.state.condition} />
In the MyStackNav you could say:
const MyStackNav = props => StackNavigator({
Tabs:{
screen: TabNavigator({
Tab1: { screen: TabScreen1},
Tab2: { screen: TabScreen2},
Tab3: { screen: TabScreen3},
...(props.condition? { Tab4: {
screen: TabScreen4
}} : {})
})
}
StackScreen1:{
screen: StackScreenOne,
},
StackScreen2:{
screen: StackScreenTwo,
},
})
You don't need to create a React.component, to pass down props.
You can also expand it a bit, in case you'd like to do a little bit more in your component:
const MyStackNav = (props) => {
const { condition } = props;
return StackNavigator({
Tabs: {
screen: TabNavigator({
Tab1: {
screen: TabScreen1
},
Tab2: {
screen: TabScreen2
},
Tab3: {
screen: TabScreen3
},
...(condition ? {
Tab4: {
screen: TabScreen4
}
} : {})
})
}
StackScreen1: {
screen: StackScreenOne,
},
StackScreen2: {
screen: StackScreenTwo,
},
})
}
Related
My App.js looks like this which has StackNavigator
export default class App extends Component {
render() {
return (
<AppStackNavigator />
);
}
}
const AppStackNavigator = new StackNavigator({
LoginScreen: { screen: LoginScreen },
DashboardScreen: { screen: DashboardScreen },
ImportantNumberScreen: { screen: ImportantNumberScreen },
EventListScreen: { screen: EventListScreen },
});
I have to create bottom navigation so i am using react-navigation component createBottomTabNavigator where i want to set header as null
so i tried following code
static navigationOptions = {
header: null,//works with createStackNavigator but not with createBottomTabNavigator
}
Also tried
export default createBottomTabNavigator({
HomeScreen: {screen : HomeScreen,navigationOptions:{header:null}},
GuestCardScreen: GuestCardScreen,
MoreScreen: MoreScreen,
StatementScreen: StatementScreen,
});
but unfortunately these code not working with createBottomTabNavigator
I am using
"react-navigation": "^2.17.0"
Node version v10.11.0
npm version v6.4.1
TabBar
const MainAppTab = createBottomTabNavigator({
[HOME_STACK]: {
screen: Home,
},
[NOTIFACATION]: NotificationContainer,
[STINGER]: StingerContainer,
[MESSAGE]: MessageContainer,
[USER_PROFILE]: ProfileContainer
},
},
{
// settings
});
Main Navigator
const AppNavigator = createStackNavigator({
[WELCOME]: {
screen: WelcomeContainer,
},
// other screens
[MAIN]: {
screen: MainAppTab,
navigationOptions: {
header: null, <----- this will help you
},
},
}, {
initialRouteName: WELCOME,
},
});
you should set tab bar options like below:
const TabNav = createBottomTabNavigator({
HomeScreen: {screen : HomeScreen},
GuestCardScreen: GuestCardScreen,
MoreScreen: MoreScreen,
StatementScreen: StatementScreen,
});
// just for hide tabbar header
const StackNavForTabs = createStackNavigator({
tab: TabNav,
}, {
header: null,
headerMode: 'none'
});
//your main stack navigator
export default AppStack = createStackNavigator({
otherStackRoutes: OtherRoute,
tabStack: StackNavForTabs,
});
I used TabNavigator in the main.js file
const TabsNav = TabNavigator({
sccreen1: {
screen: screen1
},
screen2: {
screen: screen2
},
},
{
navigationOptions: ({ navigation }) => ({
tabBarVisible: false,
}),
});
I used the following code in the today.js file
class TodayMenu extends Component {
static navigationOptions = {
title: 'today',
headerBackTitle: null,
}
}
export default TodayMenu = StackNavigator(
{
First: {screen: TodayMenu},
Second: {screen: DetailsProduct}
}
)
I'm going to transition the screen today to screen1 or screen2, which code should i use?
if you want to have stackNavigator you should define a button or somthing like that and use
this.props.navigation.navigate('destination screen')
you can find more about it hear
I'm using react-navigation.
I'm using createStackNavigator inside createBottomTabNavigator.
I want to hide tab bar for SignInScreen that is inside AccountTab but it's not working.
export default createBottomTabNavigator({
HomeTab: { screen: createStackNavigator ({
HomeTabScreen : { screen:HomeTabScreen },
ProductScreen : { screen:ProductScreen },
}),
initialRouteName: 'HomeTabScreen',
},
AccountTab: { screen: createStackNavigator ({
AccountTabScreen : { screen:AccountTabScreen },
RegisterScreen : { screen:RegisterScreen },
SignInScreen : { screen:SignInScreen },
}),
initialRouteName: 'AccountTabScreen',
},
},
{
initialRouteName: 'HomeTab',
navigationOptions: ({ navigation }) => ({
tabBarLabel: ({ focused, tintColor }) => {
const { routeName } = navigation.state;
let name;
if (routeName === 'HomeTab') {
name = "Home";
} else {
name = "Account";
}
return <Text style={[styles.titleStyle, focused ? styles.titleSelectedStyle : {}]}>{name}</Text>;
},
}),
});
I'm try three method but it's not working.
methods are following
1) I was applied tabBarVisible:false in above code so it hide tab bar for all screen.
2) I was applied function for tabBarVisible like tabBarLabel function in above code.
3) I was applied tabBarVisible:false in navigationOptions inside SignInScreen.
How to hide tabbar for SignInScreen?
There is a git thread that might help you:
https://github.com/react-navigation/react-navigation-tabs/issues/19#issuecomment-410857516
Basically you should try changing your AccountTab navigation options like this:
AccountTab: {
screen: createStackNavigator ({
AccountTabScreen : { screen:AccountTabScreen },
RegisterScreen : { screen:RegisterScreen },
SignInScreen : { screen:SignInScreen },
}),
initialRouteName: 'AccountTabScreen',
navigationOptions: ({navigation}) => {
let { routeName } = navigation.state.routes[navigation.state.index];
let navigationOptions = {};
if (routeName === 'SignInScreen') {
navigationOptions.tabBarVisible = false;
}
return navigationOptions;
}
},
const NestedNavigator = StackNavigator({
ScreenOne: {
screen: ScreenOneComponent
},
ScreenTwo: {
screen: ScreenTwoComponent
}
});
class NestedNavigatorWrapper extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<DashboardNavigator screenProps={{ rootNavigation: this.props.navigation }} />
);
}
}
const AppNavigator = StackNavigator({
Home: {
screen: HomeComponent
},
Nested: {
screen: NestedNavigatorWrapper
}
});
If you want to hide tabNavigation in the screen2(part of the StackNavigator then,
navigationOptions: ({navigation}) => {
let {routeName} = navigation.state.routes[navigation.state.index];
let navigationOptions = {};
console.log('Route Name=' + JSON.stringify(routeName));
if (routeName === 'Screen') {
navigationOptions.tabBarVisible = false;
}
return navigationOptions;
Hope it's ok.
I Can't understand how custom header it's supposed to work.
I just want to send static properties to my Header depending on which route is selected.
I have:
export default AppNavigator = StackNavigator({
Index:{
screen: BottomNavigator,
}
},{
navigationOptions: {
header: AppHeader,
},
headerMode:'float',
})
And my BottomNavigator is:
const BottomNavigator = TabNavigator({
TabMenu1: {
screen: () => <Text> Resumé </Text>,
navigationOptions: {
title: 'Resumé'
}
},
TabMenu2: {
screen: () => <Text> Sells </Text>,
navigationOptions: {
title: 'Sells'
}
},
},{
tabBarComponent: BottomNavigation
});
I'm expecting {props.title} in my custom header, is that right?
Additional info: My full route stack is:
AuthNavigator have a wrapper that is connected to redux and have:
const AuthNavigator = StackNavigator({
SignedIn: {
screen: MainNavigator
}
},{
headerMode:'none',
initialRouteName: 'SignedIn'
});
MainNavigator:
const MainNavigator = StackNavigator({
Drawer: {
screen: DrawerNav
},
}, {
headerMode:'none',
});
DrawerNav:
const DrawerNav = DrawerNavigator({
Menu1: {
screen: AppNavigator
},
}, {
contentComponent: DrawerNavigation,
drawerWidth: 300
});
AppNavigator and BottomNavigator are described above
for React Navigation 5 this works
props.scene.descriptor.options.title
You can specify title like this :
RouteName:
{
screen: RouteScreen,
navigationOptions: ({navigation}) => ({
title: navigation.state.params.title || 'StaticTitle'
})
}
Where navigation.state.params.title is the title you send as a params when you navigate (so if you want to add a variable for exemple). If you just want to use a static title, just use title: 'StaticTitle'
export const Navigator = StackNavigator(routes, {
headerMode: 'screen',
navigationOptions: ({ navigation }) => ({
header: props => <Header {...props} />,
}),
})
I did find a work around but it seems pretty verbose for what seems to be a common use case..
// Header.js
...
render() {
const { getScreenDetails, scene } = this.props
const details = getScreenDetails(scene)
return (
<View>
<Text>{details.options.title}</Text>
<View>
)
Resolved with a code extracted of Header.js file of react-navigation:
The right way to get the title inside a custom header is:
const sceneOptions = props.getScreenDetails(props.scene).options;
const sceneTitle = sceneOptions.title;
Thanks all!
I want to navigate to to the same screen but with different params.
so imagine
navigate to MyRouteName
on this screen click a button which should navigate me to MyRouteName but with different params.
currently I've tried
this.props.navigation.navigate('MyRouteName', {param1: 'new val'})
and
const setParamsAction = NavigationActions.setParams({
params: { param1: 'new val'},
key: 'mrn-new_val',
})
this.props.navigation.dispatch(setParamsAction)
Neither work. Neither the docs nor github issues I found provide clear guidance on this.
How do i accomplish this?
Update: in response to comment below
I'm using a stacked Navigator as my root, which leads to a DrawerNavigator
// MyDrawer.js
// ...
const MyDrawer = DrawerNavigator(
{
MyRouteName: {
screen: MyScreen,
},
},
{
initialRouteName: 'MyRouteName',
contentOptions: {
activeTintColor: '#e91e63',
},
contentComponent: props => <DrawerScreen {...props}/>,
}
);
export default MyDrawer;
// MyScreen.js
class MyScreen extends React.Component{
//..
//.. stuff goes here
//..
drillDown(newVal){
const setParamsAction = NavigationActions.setParams({
params: { param1: newVal },
key: 'ms-${newVal}',
})
this.props.navigation.dispatch(setParamsAction)
}
//..
//.. more stuff
//..
}
My final implementation based on #benneygenel's answer below.
const MyDrawer = DrawerNavigator({
MyRouteName: {
screen: StackNavigator({
DrillDown:{
screen: MyScreen,
},
}, {
headerMode: 'none',
}),
},
});
(MyScreen defines it's own header)
You can use a StackNavigator inside the Drawer and navigate like a normal StackNavigator.
const MyDrawer = DrawerNavigator({
MyRouteName: {
screen: StackNavigator({
DrillDown: {
screen: MyScreen
}
}),
},
});
export default MyDrawer;