React Native multiple "Root" Views? - react-native

Building my first React Native Application.
Currently I am using this way of navigating through different views.
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name={"Start"} component={Welcome}/>
<Stack.Screen name={"LoginMethod"} component={LoginMethod}/>
<Stack.Screen name={"SocialSecurityNumber"} component={SocialSecurityNumber}/>
<Stack.Screen name={"NorBankId"} component={NorBankId}/>
<Stack.Screen name={"NorBankIdMobile"} component={NorBankIdMobile}/>
<Stack.Screen name={"NorBankIdMobileUsername"} component={NorBankIdMobileUsername}/>
<Stack.Screen name={"NorBankIdMobilePassword"} component={NorBankIdMobilePassword}/>
<Stack.Screen name={"Fingerprint"} component={Fingerprint}/>
<Stack.Screen name={"MainView"} component={MainView}/>
</Stack.Navigator>
</NavigationContainer>
This setup, is for the onboarding process from a new customer.
So the first component is Welcome and then the user moves along, with the option to go backwards.
However, when they are done with the process (the last screen), I want them to arrive to a "Screen" that is not ontop of the Stack, but it's own "Root" or "Base" View.
What I have looked into
I have tried having multiple stack navigators which is a no no. Also checked the Tab navigator, however this creates a tab menu below me screen, which I do not want.
Is it possible to do what I want, or do I need to restructure the way I have my setup now?
Thank you for your time, Stay Safe!

Why you don't want to use multiple Stack-Navigators?
My approach would be:
<NavigationContainer>
{ inWelcomeProcess && <WelcomeNavigator/>}
<AuthNavigator/>
</NavigationContainer>
const AuthStackNavigator = createStackNavigator();
export const AuthNavigator = () => {
return (
<AuthStackNavigator.Navigator screenOptions={defaultNavOptions}>
<AuthStackNavigator.Screen name="Auth" component={AuthScreen} options={authScreenOptions}/>
// Your other screens (after finishing the on-boarding) should go here
</AuthStackNavigator.Navigator>
);
};
const WelcomeStackNavigator= createStackNavigator();
export const WelcomeNavigator= () => {
return (
<WelcomeStackNavigator.Navigator screenOptions={defaultNavOptions}>
// Your On-Boarding process screens here
</WelcomeStackNavigator.Navigator>
);
};

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)

Expo React-Native Web Browser Back Button

I'm looking at using React-Native and Expo to build a web app. The only real issue I'm running into is allowing the use of the browser back button. I'm currently using #react-navigation/native to navigate between screens.
Unfortunately, when changing screens, the browser doesn't seem to register this as a change of page and so the browser back button never works. I could certainly use the standard back button used within the app to navigate back but I'd like people to be able to use the browser back button as that's more intuitive. I'm using the following in my App.js:
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
const Stack = createNativeStackNavigator();
const App = () => {
...
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Home"
component={HomeScreen}
options={{ headerShown: false }}
/>
<Stack.Screen
name="Settings"
component={SettingsScreen}
options={{ headerShown: false }}
/>
</Stack.Navigator>
</NavigationContainer>
)
};
export default () => {
return (
<App />
);
};
So, is it possible using Expo and React-Native to allow the use of the browser back button for apps built for the web?

React Navigation 6.x Initial Route Not Working

I'm using React Navigation 6.x's linking with Expo so that when a user clicks on a notification they are directed to the appropriate part of my application to interact with the new information. When my app is backgrounded (running in the background) and a user clicks on a notification they are redirected to the screen they need to be at, which works perfectly fine. However, when the app is killed and the user clicks on a notification, they are taken directly to the screen for which the url is provided and they cannot press back to navigate elsewhere in my application. I tried to resolve this by using the initialRouteName prop like is shown in the docs (link: https://reactnavigation.org/docs/configuring-links/#rendering-an-initial-route), but I cannot get it to work. For further clarification, when I mentioned above that I am able to get linking working it is in relation to the direct SettingsScreen, AddFriendScreen, and MessagingScreen links. What I cannot get working is the specific block of code inside the liking object that starts with HomeScreen. What I believe may be causing the issue is that I am trying to set my initialRoute as a screen within HomeScreen's Tabs.Navigator and then trying to route to a screen within my Stack.Navigator. However, the docs show that this is possible (link: https://reactnavigation.org/docs/configuring-links/#rendering-an-initial-route).
My code:
const linking = {
prefixes: [prefix],
config: {
screens: {
HomeScreen: {
initialRouteName: "Chats",
screens: {
AddFriendScreen: "addFriend",
CreateChatScreen: "createChatScreen",
Friends: "friends",
MessagingScreen: 'messagingScreen/:chatRoomId'
}
},
SettingsScreen: "SettingsScreen",
AddFriendScreen: "AddFriendScreen",
MessagingScreen: 'MessagingScreen/:chatRoomId'
},
}
};
<NavigationContainer linking={linking} theme={MyTheme} >
<Stack.Navigator>
{!authState.value ?
<>
<Stack.Screen name="LoginScreen" component={LoginScreen} />
<Stack.Screen name="SignUpScreen" component={SignUpScreen} />
<Stack.Screen name="ForgotPasswordScreen" component={ForgotPasswordScreen} />
</>
:
<>
<Stack.Screen name="HomeScreen" component={HomeScreen} />
<Stack.Screen name="MessagingScreen" component={MessagingScreen} />
<Stack.Screen name="SettingsScreen" component={SettingsScreen} />
<Stack.Screen name="CreateChatScreen" component={CreateChatScreen} />
<Stack.Screen name="AddFriendScreen" component={AddFriendScreen} />
</>
}
</Stack.Navigator>
</NavigationContainer>
const HomeScreen = () => {
return (
<Tabs.Navigator>
<Tabs.Screen name="Chats" component={ChatScreen} />
<Tabs.Screen name="Friends" component={FriendsScreen} />
<Tabs.Screen name="Profile" component={ProfileScreen} />
</Tabs.Navigator>
)
}
Hmm, I would put any screen that I would like to access in multiple navigators at the root level so that they can both reach it.
For my own project, I have a root stack with a dedicated auth stack and an app/home stack (which is a tab nav like your HomeScreen). And outside that I have all my modal and root screens that I'd like other navigators to access (Because I really have two Home tab navigators the user can switch between.)
Idk if putting all of your screens listed after HomeScreen outside of that object will help your situation, but you can try that.

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

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?

How to specify a default screen for react native stack navigator?

I want to navigate between two screens in my RN application: Daily and AllTodos. I want to make sure that when the navigator renders Daily by default. This is the code which I have used which accords the documentation :
const StackNavigator = ({component}) => {
return (
<NavigationContainer independent={true}>
<Stack.Navigator initialRouteName="Daily">
<Stack.Screen
name="Daily"
component={Daily}
options={{headerShown: false}}
/>
<Stack.Screen
name="AllTodos"
component={AllTodos}
options={{headerShown: false}}
/>
</Stack.Navigator>
</NavigationContainer>
);
};
But still AllTodos page is rendered by default. Where am i going wrong?
You don't need to destructure the 'component' props. Take it off.
const StackNavigator = ({component}) // take off the component props => {