(also asked in https://github.com/react-navigation/react-navigation/issues/4059#issuecomment-453100740)
I have replaced a static TabNavigator with a dynamic one, and things seem to work.
However, props that have been passed as expected are not passed any more the same way.
Any idea how to fix this? Either by having the props passed as in the static solution, or by passing the required props (this.props.navigation).
This is my top navigator:
export default createDrawerNavigator({
Drawer: MainDrawerNavigator,
Main: MainTabNavigator
}, {
contentComponent: props => <Drawer {...props} />,
});
This the static Tab Navigator and one of the Stacks:
const ProfileStack = createStackNavigator({
Profile: {
screen: Profile,
navigationOptions: () => ({
title: 'Profile'
})
}
}, {
initialRouteName: 'Profile'
});
ProfileStack.navigationOptions = {
tabBarLabel: 'Profile',
tabBarIcon: ({ focused }) => (
<TabBarIcon
focused={focused}
name= 'md-person' />
)};
const MainTabNavigator = createBottomTabNavigator({
RequestStack,
ProfileStack
}, {
headerMode: 'none',
initialRouteName: ProfileStack
});
And the Profile
screen:
import React from 'react';
import { View, TouchableOpacity } from 'react-native';
import { Container, Header, Content, Text
} from 'native-base';
export default class Profile extends React.Component {
static navigationOptions = {
header: null
};
constructor(props) {
super(props);
}
render() {
console.log('in Profile. this.props:');
console.log(this.props);
return (
<Container style={styles.container}>
<Header>
<TouchableOpacity
onPress={() => this.props.navigation.openDrawer()}>
<Icon name="md-more" />
</TouchableOpacity>
</Header>
<Content>
<Text>aaa</Text>
</Content>
</Container>
);
}
}
A click on the "md-more" icon opens the drawer (this.props.navigation.openDrawer).
Using a dynamic tab navigator - openDrawer is not passed any more to 'Profile'.
when I replace the above static Tab Navigator with the following Dynamic one, this.props.navigation.openDrawer is not passed and therefore not defined in 'Profile' (Profile doesn't change, the change is only in the bottom tab navigator).
Here is the dynamic Tab Navigator:
export default class DynamicTabNavigator extends React.Component {
constructor(props) {
super(props);
}
_tabNavigator() {
let tabs = {};
const a = 2;
if (a > 1) { // the actual line is obviously different, I am trying to simplify the example
tabs = { RequestStack, ManageStack, MessagesStack, ProfileStack };
} else {
tabs = { WorkStack, ManageStack, MessagesStack, ProfileStack };
}
console.log('in _tabNavigator. this.props.navigation:');
console.log(this.props.navigation);
return createBottomTabNavigator(tabs, {
headerMode: 'none',
});
}
render() {
const Tabs = this._tabNavigator.bind(this)();
return (
<Tabs/>
);
}
}
This is the output of console.log() from DynamicTabNavigator:
in _tabNavigator. this.props.navigation:
Object {
"actions": Object {
"closeDrawer": [Function closeDrawer],
"goBack": [Function goBack],
"navigate": [Function navigate],
"openDrawer": [Function openDrawer],
"setParams": [Function setParams],
"toggleDrawer": [Function toggleDrawer],
},
"addListener": [Function addListener],
"closeDrawer": [Function anonymous],
"dangerouslyGetParent": [Function anonymous],
"dispatch": [Function anonymous],
"getChildNavigation": [Function getChildNavigation],
"getParam": [Function anonymous],
"getScreenProps": [Function anonymous],
"goBack": [Function anonymous],
"isFocused": [Function isFocused],
"navigate": [Function anonymous],
"openDrawer": [Function anonymous],
"router": undefined,
"setParams": [Function anonymous],
"state": Object {
"key": "Main",
"params": undefined,
"routeName": "Main",
},
"toggleDrawer": [Function anonymous],
}
This is the output of console.log() from Profile, when DynamicTabNavigator is in place:
(I expected all props, like for instance, openDrawer, to be the same as for DynamicTabNavigator, and I don't understand why they aren't)
in Profile. this.props:
Object {
"appMode": "WORK_MODE",
"dispatch": [Function anonymous],
"navigation": Object {
"actions": Object {
"dismiss": [Function dismiss],
"goBack": [Function goBack],
"navigate": [Function navigate],
"pop": [Function pop],
"popToTop": [Function popToTop],
"push": [Function push],
"replace": [Function replace],
"reset": [Function reset],
"setParams": [Function setParams],
},
"addListener": [Function addListener],
"dangerouslyGetParent": [Function anonymous],
"dismiss": [Function anonymous],
"dispatch": [Function anonymous],
"getChildNavigation": [Function getChildNavigation],
"getParam": [Function anonymous],
"getScreenProps": [Function anonymous],
"goBack": [Function anonymous],
"isFocused": [Function isFocused],
"navigate": [Function anonymous],
"pop": [Function anonymous],
"popToTop": [Function anonymous],
"push": [Function anonymous],
"replace": [Function anonymous],
"reset": [Function anonymous],
"router": undefined,
"setParams": [Function anonymous],
"state": Object {
"key": "id-1547113035295-8",
"routeName": "Profile",
},
},
"screenProps": undefined,
}
Questions regarding @dentemm's solution:
I a not sure how to implement your solution...
- Lets say that I have in my
TabRoutes
the three screens that you specified in your example - In my redux state I have a variable called 'appState'. If it is true I want to display first & second, if false first & third.
Here is the code that I wrote based on your example. I am not sure, however, which component is included in
CustomTabBar
. Can you elaborate?import React from 'react'; class CustomTabBar extends React.Component { render() { // a tab bar component has a routes object in the navigation state const { navigation } = this.props; // appState is extracted from redux state, see below if (this.props.appState) { return ( <View> <??? name='First' onPress={this.navigationHandler} focused={navigation.state.index === index} /> <??? name='Second' onPress={this.navigationHandler} focused={navigation.state.index === index} /> </View> ); } else { return ( <View> <??? name='First' onPress={this.navigationHandler} focused={navigation.state.index === index} /> <??? name='Third' onPress={this.navigationHandler} focused={navigation.state.index === index} /> </View> ); } } navigationHandler = (name) => { const {navigation} = this.props; navigation.navigate(name); } } const mapStateToProps = state => { const { appState } = state.app; return { appState }; }; export default connect(mapStateToProps)(CustomTabBar);
<Tabs navigation={this.props.navigation}/>
– ValdaXD