Render one component over another at a certain route with react-navigation - react-native

I have a stack navigator with react router, using #react-navigation/native-stack. My home screen is a map, and I have a few menu components:
export const App = () => {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Home">
<Stack.Screen
name="Home"
options={{ headerShown: false }}
component={Home}
/>
<Stack.Screen
name="SignIn"
component={SignIn}
/>
</Stack.Navigator>
</NavigationContainer>
)
}
Home is the map component, and SignIn, as well as some other components, are menu components that take over the screen when navigated to, pushing Home out of the way, as expected.
I want to be able to 'navigate' to another component at a certain route, call it Overlay. When routed here, I want to show the home screen, with an Overlay component laid over the top of part of the Home component, while still maintaining interactivity with the part of the Home screen that is not covered. However, if I do this:
<Stack.Navigator initialRouteName="Home">
<Stack.Screen
name="Home"
options={{ headerShown: false }}
component={Home}
/>
<Stack.Screen
name="Overlay"
component={Overlay}
/>
</Stack.Navigator>
Then the Home screen moves away, and is replaced by Overlay.
How can I show a component overlaid over the top of my Home screen when the user is routed to a certain route? This is something easily done with react-router, but I'm not sure if there is a parallel in react-navigation. Is react-navigation not the right approach for this? Is it better to conditionally render the Overlay component based on a state/redux variable?

Related

Hide an element from a Navigation Container on a specific screen on React Native

My main App is the following
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" ... />
<Stack.Screen name="LogIn" ... />
<Stack.Screen name="Profile" ... />
</Stack.Navigator>
<NavBar />
</NavigationContainer>
);
}
It consists in some screens, and then a bottom navigation bar that is present in all the screens.
My question is, is there a way to hide the NavBar element in a specific screen or to specifically show it without having to manually put it in every screen?
I have tried:
Using the useRoute function to return nothing if the route name was an specific one
Manually putting the NavBar on every single screen (would solve it, but is not very efficient)

React Navigation Tab Screens don't show up as separate screens in history

I have a Tab Navigator with 3 screens: Home, Camera, and Profile. I then have a stack navigator which references the tab navigator, and have a screen in this stack navigator called Camera2.
const Navigation = () => {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={TabNavigator} />
<Stack.Screen name="Camera2" component={Camera2Screen} />
</Stack.Navigator>
</NavigationContainer>
);
};
const TabNavigator = () => {
return (
<Tab.Navigator backBehavior="history" initialRouteName="Home">
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="ToCamera" component={ToCameraScreen} />
<Tab.Screen name="Profile" component={ProfileScreen} />
</Tab.Navigator>
);
};
Suppose I start at the Home screen, then navigate to the Camera screen by selecting the camera tab. Then in the Camera screen I use navigation.replace("Camera2"). At this point, in the Camera2 screen I would want the navigation history to look like [Home, Camera2] since the Camera screen had been removed from history. However, what I end up seeing is [Camera2].
After doing some research I realized this was happening since the tab navigator acts as a single screen in the stack navigator, so seperate tabs show up as a single screen in navigation history. So if I remove the Camera screen from history it essentially removes all Tab Navigator screens (including the Home screen).
I realize this is the expected behaviour but I was wondering how I can get the desired behaviour.

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 stack navigator disable go back ability

How to disable ability to go back
I have a functional component
export default function App(){
createHomeStackNavigator = () =>
<Stack.Navigator screenOptions={{
headerShown: false
}}>
<Stack.Screen
name="Login"
component={Login}
/>
<Stack.Screen
name="Home"
children={createHomeTabNavigator}
/>
</Stack.Navigator>
return(
<NavigationContainer>
{createHomeStackNavigator()}
</NavigationContainer>
)
When user goes to Home, its onclick on Login component then he cant go back to the login by any swipe on ios, back button on Android and other ways
Probably you should use navigation.reset();

react-navigation always mount initial screen when StackNavigator renders (v5)

In react-navigation v5, is there a way to always mount/render an initial screen to be the first screen in the stack when the StackNavigator renders?
You need to pass initialRouteName prop inside Stack.Navigator of your application.
Example Code :
<NavigationContainer>
<Stack.Navigator
initialRouteName="HomeScreen" // Add this to set initial screen
screenOptions={{
headerShown: false,
}}>
<Stack.Screen name="HomeScreen" component={HomeScreen} />
<Stack.Screen name="UploadScreen" component={UploadScreen}/>
</Stack.Navigator>
</NavigationContainer>
Refer more information
Use initialRouteName props (The name of the route to render on first load of the navigator) if you want a specific screen, otherwise the first stack screen will be rendered by default.
Doc - https://reactnavigation.org/docs/stack-navigator/