Render a nested Tab screen in a Stack Navigator - react-native

Seems it should be so simple but I can't figure it out. I have a nested Tab Navigator inside a Stack Navigator like so:
function App(){
const Main = () =>{
<Tab.Navigator initialRouteName={"Players"}>
<Tab.Screen name="Players" component={FindPlayers} />
<Tab.Screen name="Requests" component={MatchRequests} />
</Tab.Navigator>
}
....
return (
<NavigationContainer>
<Stack.Navigator initialRouteName={"Main"} >
<Stack.Screen name="Main" component={Main}/>
<Stack.Screen name="CourtPicker" component={CourtPicker}/>
</Stack.Navigator>
</NavigationContainer>
)}
It renders a blank screen with the Header that says "Main" instead of rendering the FindPlayers component.
My expectation is that I've defined an initial route Main which should render my Main component which is a Tab navigator, which should in turn render the Players component because I've defined the initialRouteName as such.
What am I doing wrong here?

according to Nesting navigators
Try :
<Stack.Screen name="Main" component={Main} options={{
headerShown: false,
}}/>

Related

Structure for nested navigation with react-native-navigation

I am currently building my first app using react-native and i am struggeling with the right structure for nested navigation using react-native-navigation .
My app should be navigatable using a Tab-bar. On every screen of that Tab-bar I might need to have a Stack navigation available.
App.js:
<NavigatonContainer>
<BottomTab.Navigator>
<BottomTab.Screen name="Screen1" component={Screen1}/>
<BottomTab.Screen name="Screen2" component={Screen2}/>
<BottomTab.Screen name="Screen3" component={Screen3}/>
<BottomTab.Navigator/>
<NavigationContainer/>
Now if i want to use a Stack navigation inside Screen1, what would be the best approach? My approach would be to move all content that should be display when the first Tab is active to a new screen called "Screen1Start" and then having following code on "Screen1".
Screen1.js:
<Stack.Navigator>
<Stack.Screen name="Screen1Start" component={Screen1Start}/>
<Stack.Screen name="Screen1Settings" component={Screen1Settings}/>
<Stack.Screen name="Screen1Details" component={Screen1Details}/>
</Stack.Navigator>
Is that the right thing to do? Are there better approaches to this? Thanks for your help!
You can have a stack inside of a stack and then navigate to each individually with navigation.navigate('name'). In the react navigation docs you can read more about navigating inside nested navigators here.
Pretty quick example would be:
function Home() {
return (
<Tab.Navigator>
<Tab.Screen name="Feed" component={Feed} />
<Tab.Screen name="Messages" component={Messages} />
</Tab.Navigator>
);
}
function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Home"
component={Home}
options={{ headerShown: false }}
/>
<Stack.Screen name="Profile" component={Profile} />
<Stack.Screen name="Settings" component={Settings} />
</Stack.Navigator>
</NavigationContainer>
);
}
Here you can see that Home is a stack of feed and messages and then you have individual screens for Profile and Settings. Like so you can have another stack instead of Profile or Settings binded by another navigator such as toptab or bottomtab.
The react navigation docs explain this very detailed and easy to understand. I would recommend you to read from start to finish so you have a deeper understanding of the navigation.

What is the difference between nesting a Drawer navigator inside a Stack navigator, or the opposite?

In the documentation for version 6.x of React Navigation, in fundamentals, Navigating to a screen in a nested navigator, they have an example of nesting a Drawer navigator inside of a Stack navigator.
function Root() {
return (
<Drawer.Navigator>
<Drawer.Screen name="Home" component={Home} />
<Drawer.Screen name="Profile" component={Profile} />
<Stack.Screen name="Settings" component={Settings} />
</Drawer.Navigator>
);
}
function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Root"
component={Root}
options={{ headerShown: false }}
/>
<Stack.Screen name="Feed" component={Settings} />
</Stack.Navigator>
</NavigationContainer>
);
}
Why is it shown like this and not the Drawer as the parent navigator and the Stack inside?
I've seen other examples that do this (Drawer parent, Stack inside) but I don't understand what the difference in terms of layouts or the final UI.
Asked somewhere else and got this answer:
If stack is nested inside drawer - you can still open drawer in any
stack screen, etc
if drawer is nested inside stack - drawer will be
only present in the screen that drawer is, and cannot be seen as other
screens will render above it

React Native Navigation pass dynamic data when rendering

changeTheme(){
this.setState({darktheme:!this.state.darktheme})
}
render()
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Home">
<Stack.Screen name="Home" component={HomeScreen} darkT={this.state.darktheme==true} />
<Stack.Screen name="Settings" component={SettingsScreen} changeTheme={this.changeTheme} darkT={this.state.darktheme==true} />
</Stack.Navigator>
</NavigationContainer>
);
}
In the settings page. I want to change the theme using this.props.changeTheme() it is supposed to change the state of the app and the whole app will re-render. But it doesn't work like that, the theme is not being changed. What am I doing wrong here?
When I log this.props.darkT it returns false even after I called the function changeTheme()
You can try this:
<Stack.Screen name="Settings">
{ () => <SettingsScreen darkT={!!this.state.darkTheme} changeTheme={this.changeTheme} /> }
</Stack.Screen>
In the Settings screen darkT and changeTheme will be available as props so you can access with this.props.darkT and this.props.changeTheme

React-native going back from a nested navigation container does not work

I am creating a nested navigation container in react-native and the stack looks like this:
-Main Navigation Container:
- Home
- Market Navigation Container:
- Market
- Cart
- About
When I go to home or about and go back, it works properly. However, when I go back from Market or cart (Which I expect to go to the Home page) it shows an error saying:
The action 'POP' with payload {"count":1} was not handled by any navigator.
Is there any screen to go back to?
This is a development-only warning and won't be shown in production.
This is my code for the main navigation container:
<NavigationContainer independent={true}>
<Stack.Navigator>
<Stack.Screen options={myOptions} name="Home" component={Home} />
<Stack.Screen
options={{ headerShown: false }}
name="MarketNavigation"
component={MarketNavigation}
/>
<Stack.Screen options={myOptions} name="About" component={About} />
</Stack.Navigator>
</NavigationContainer>
And this is my code for the market navigation:
<NavigationContainer ref={navigationRef} independent={true}>
<Stack.Navigator>
<Stack.Screen
options={myOptions}
name="Market"
component={Market}
/>
<Stack.Screen
options={myOptions}
name="Cart"
component={Cart}
/>
</Stack.Navigator>
</NavigationContainer>
I faced this when navigating to nested navigator using "screen" option like this:
navigation.navigate('Root', {
screen: 'Settings'
})
;
As mentioned in the documentation:
By default, when you navigate a screen in the nested navigator, the
specified screen is used as the initial screen and the initial route
prop on the navigator is ignored.
To solve this you should use "initial: false" like so:
navigation.navigate('Root', {
screen: 'Settings',
initial: false,
});
Could you add in the code where you navigate from Home to MarketNavigation and back?

React Navigation hide/show navigation bar

I am facing a problem with hiding or showing the navigation bar with ReactNavigation 5.x.
For example if I have a navigation stack with ScreenA, ScreenB & ScreenC. ScreenA shouldn't show the navigation bar, but on moving to ScreenB or ScreenC the bar should be visible. On popping to ScreenA, the bar should no longer be there. I have used the following code, but that makes the bar hidden always. This has to be achieved in both iOS and Android.
class App extends Component {
render() {
return(
<NavigationContainer>
<Stack.Navigator screenOptions={{headerShown: false}}>
<Stack.Screen
name="Login"
component={LoginScreen}/>
<Stack.Screen
title='Parent Info'
name='ParentInfo'
component={ParentInfoScreen}
/>
</Stack.Navigator>
</NavigationContainer>
)}
}
Each screen also has an options prop so instead of using screenOptions on stack.navigator use options on stack.screen like this:
<Stack.Navigator>
<Stack.Screen
options={{headerShown: false}}
name="Login"
component={LoginScreen}
/>
<Stack.Screen
title="Parent Info"
name="ParentInfo"
component={ParentInfoScreen}
/>
</Stack.Navigator>
Then you can specify by screen