Reputation: 659
Question - How to properly use React Navigation's TabNavigator container component inside another React component that acts just as wrapper component?
What I want to achieve - Basically I want the appbar and tabbar both to be displayed - appbar on the top, tabbar (TabBarTop) just beneath it, a very common design pattern.
I have tried a couple of ways.
Method #1 (Nesting inside StackNavigator)
Tab.js
export const Tab = TabNavigator({
Tab1: { screen: Tab1Container },
Tab2: { screen: Tab2Container }
}, {
tabBarComponent: TapBarTop,
tabBarPosition: 'top'
});
AppBar.js
class AppBarComponent extends Component {
static navigationOptions = { header: null }
render() {
return (
<View>
*some more views, buttons blah blah here
</View>
)
}
}
export default AppBarComponent;
and I use them inside StackNavigator, like
export default StackNavigator({
stack1: { screen: AppBarComponent },
stack2: { screen: Tab }
});
This results in only 1 stack to be displayed at a given time which is exactly how it works. And I don't have anything to do with initialRouteName
.
Method #2 (wrapping inside another component)
<View style={{ flex: 1 }}>
<AppBarComponent />
<Tab />
</View>
This on the contrary displays both components but this.props.navigation.navigate('somepath') or push() or pop() or replace() doesn't work from inside and . But this.props.navigation and its methods all are available inside those components.
PS - I'm using React Navigation v1 and running on iOS
Upvotes: 4
Views: 3521
Reputation: 659
@bennygenel your answer is definitely useful in addressing the problem. I kind of fed wrong information when I talk about having components inside TabNavigator. Well, instead of dumb components, there were multiple redux containers inside the TabNavigator as screens and the entire TabNavigator wrapped in a Dumb component. I have edited my question sincerely.
Though this.props.navigation
exists both inside the redux containers and the wrapper component, the navigation stack reference was different for them which is why methods such as navigate
or goBack()
were not working.
The solution was simple. Passing the navigation stack reference as screenProps
to the wrapper component solves this issue.
<View style={{ flex: 1 }}>
<AppBarComponent />
<Tab screenProps={{ rootNav: this.props.navigation }} />
</View>
Upvotes: 1
Reputation: 24660
Have a StackNavigator
with only one screen and show your TabNavigator
in that screen. Then customize header
with your custom AppBarComponent
.
header
React Element or a function that given
HeaderProps
returns a React Element, to display as a header. Setting tonull
hides header.
Sample
export default StackNavigator({
stack: {
screen: Tab,
navigationOptions: {
header: (HeaderProps) => (<AppBarComponent headerProps={HeaderProps} />)
}
}
});
You can wrap your component which is not a part of the stack with withNavigation
HOC.
withNavigation
is a higher order component which passes the navigation prop into a wrapped Component. It's useful when you cannot pass the navigation prop into the component directly, or don't want to pass it in case of a deeply nested child.
Sample
class AppBarComponent extends Component {
static navigationOptions = { header: null }
render() {
return (
<View>
*some more views, buttons blah blah here
</View>
)
}
}
export default withNavigation(AppBarComponent);
Upvotes: 1