How to pass params to Stack from an other Stack React Native? - react-native

My problem is that I have a Profile Stack that contains all the screens that you can reach from your / user's profile. I put this Stack to my DrawerStack and also to my HomeScreen Stack because these are the two possible ways to navigate there. But when I navigate there with some params it says that the route's params are undefined.
Profile Stack
function ProfileNavigator() {
return (
<Stack.Navigator>
<Stack.Screen name="ProfileScreen" component={Profile} />
...Other Screens
</Stack.Navigator>
);
}
Home Navigator
function HomeNavigator() {
return (
<Stack.Navigator>
<Stack.Screen name="Home" options={{headerShown: false}} component={Home} />
<Stack.Screen name="Profile" options={{headerShown: false}} component={ProfileNavigator}/>
... Other Screens
</Stack.Navigator>
);
}
Drawer Navigator
<NavigationContainer>
<Drawer.Navigator
drawerContent={props => <CustomDrawerNavigator {...props} />}
initialRouteName="Home">
<Drawer.Screen name="Home" component={BottomNavigator} />
<Drawer.Screen
name="Profile"
options={{headerShown: false}}
component={ProfileNavigator}
/>
</Drawer.Navigator>
</NavigationContainer>
Navigate to the Profile
onPress={() => props.navigation.navigate('Profile', {current_user: true})}
I can pass Params and Navigate to the Profile If I don't use Stack but then I have to add every Profile Screens to every other Stack and I don't think is it efficient. I read somewhere that the similar names can cause such a problem but I just couldn't wrap my head around the problem.

So finally I found the answer in the docs.
I had to navigate like this:
props.navigation.navigate('Profile', {
screen: 'Profile',
params: { current_user: true },
});
And I also changed the ProfileScreen name to Profile in the ProfileNavigator.

Related

React Navigation - Drawer inside Stack go back

Taking this example for the official documentation :
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={Feed} />
</Stack.Navigator>
</NavigationContainer>
);
}
They just explain here how to navigate to the Profile screen from the Feed screen like this :
navigation.navigate('Root', { screen: 'Profile' });
I would to know how can I navigate to the Feed screen from the Profile screen;
You can just use the navigation object and its navigate function since the Feed screen is nested inside the same navigator as the Root stack.
Destructure the navigation object from the props of Profile.
function Profile({navigation}) {
return ...
}
Now, just use the navigation object as follows in order to navigate to Feed.
navigation.navigate("Feed")

Navigate to Screen which are not inside BottomTabNavigator React Native

I have developed a bottomTabNavigator in react-native and I have 3 main routes which I want to show in my bottomtabnavigator which are 1) Home, 2) Profile, 3) Chat, So I wrote the following code:
const Stack = createNativeStackNavigator();
const Tab = createBottomTabNavigator();
const Navigation = () => {
return (
<>
<Tab.Navigator>
{user.authLoadingState ? (
<Tab.Screen name="Home" component={LoadingScreen} />
) : user.isLoggedIn ? (
<>
<Tab.Screen
name="Home"
component={HomeScreen}
/>
<Tab.Screen
name="Profile"
component={ProfileScreen}
/>
<Tab.Screen
name="Chat"
component={ChatScreen}
/>
<Stack.Screen name="Update" component={UpdateScreen} /> // this is the screen I don't want in my bottomTab but I want to navigate to it using useNavigation hook.
</>
) : (
<>
<Stack.Screen name="First" component={FirstScreen} />
<Stack.Screen name="SignIn" component={SignInScreen} />
<Stack.Screen name="SignUp" component={RegisterScreen} />
</>
)}
</Tab.Navigator>
</>
);
};
Now, when I go to my Profile screen, I have a button which (should) navigate to another screen which is not mentioned in my Tab Navigator definition, how can I navigate to that screen because obviously I do not want to fill my bottomTabNavigator with different screens, I only want to keep the main screens in my bottomTabNavigator not all. When I was using Stack.Navigator alone, it was fine because I could just keep all my screens under <Stack.Navigator></Stack.Navigator> and navigate to any screen using navigator.navigate(nameOfScreen) with const navigator = useNavigation(). But now, if a screen which is not mentioned inside Tab.Navigator will throw an error if I navigate saying Screen does not exists. Is there any thing I could do to make it work?
to navigate between tab and stack screen you can do this way :
const Tab = createBottomTabNavigator();
const Stack = createStackNavigator();
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen
name="Home"
component={HomeScreen}
/>
<Tab.Screen name="Profile Screen" component={StackScreens} />
<Tab.Screen
name="Chat"
component={ChatScreen}
/>
</Tab.Navigator>
</NavigationContainer>
)
function StackScreens() {
return (
<Stack.Navigator screenOptions={{ headerShown: false }} >
<Stack.Screen name="Profile" component={ProfileScreen} />
<Stack.Screen name="Update" component={UpdateScreen} /> // this is the screen I don't want in my bottomTab but I want to navigate to it using useNavigation hook.
</Stack.Navigator>
);
}
}
I'm not sure if it is exactly that you want, but you can now access from "Profile" to the "UpdateScreen" without showing it in the bottomTabNavigator

Navigating to another stack group in NavigationContainer

In my App.tsx I'm using createNativeStackNavigator and I'm trying to dismiss the modal that is "Project_Creation" and navigate to Main
<NavigationContainer>
<Stack.Navigator>
<Stack.Group>
<Stack.Screen name="Main" component={DrawerNavigator} options={{ headerShown: false }} />
<Stack.Screen name="Details" component={ChannelDetails} />
<Stack.Screen name="Profile" component={Profile} />
</Stack.Group>
<Stack.Group screenOptions={{ stackPresentation: 'modal', headerShown: false }}>
<Stack.Screen
options={{ headerTitle: 'Create Project' }}
name="Project_Creation"
component={ProjectCreationNavigator}
/>
</Stack.Group>
</Stack.Navigator>
</NavigationContainer>
I'm not sure if it's because createNativeStackNavigator is not as customizable as createStackNavigator or if I can't navigate to another Stack Group from one of the screens in ProjectCreationNavigator but it keeps getting errors.
With navigation.dismiss() I get
navigation.dismiss() is not a function
with navigation.reset({index: 0, name: "Main"}) I get
undefined is not an object
I'd love to figure out how to navigate to "Main".
Update::
I realized the problem. In separate navigator component I had NavigationContainer wrapped. When I removed that it worked

How to enable Drawer Navigation only on specific screen (e.g. Home Screen) [react native] [react navigation]

Use case of this problem is to have Drawer menu like "Settings" available only form "Home Screen". And at "Home screen" could be many buttons that link to other screens of Stack Navigation where Drawer is not available.
Main question is how to enable Drawer Navigation only on specific screen of Stack Navigator?
On below example Drawer is available on all pages of Stack. I tried with gestureEnabled but it didn't work:
const StackHome = () => (
<Stack.Navigator>
<Stack.Screen name="Home" component={Home} />
<Stack.Screen name="Example1" component={Example1} />
<Stack.Screen name="Example2" component={Example2} />
</Stack.Navigator>
);
<Drawer.Navigator initialRouteName="Home">
<Drawer.Screen name="Home" component={StackHome} />
<Drawer.Screen name="Settings" component={Settings} />
</Drawer.Navigator>
On the other hand if I try make Drawer as one of Stack screen, then I have always the same Header bar (example "Header")
Put your drawer navigator inside the home screen:
const DrawerHome = () => (
<Drawer.Navigator screenOptions={{ headerShown: true }}>
<Drawer.Screen name="Home" component={Home} />
<Drawer.Screen name="Settings" component={Settings} />
</Drawer.Navigator>
);
const StackHome = () => (
<Stack.Navigator>
<Stack.Screen
name="DrawerHome"
component={DrawerHome}
options={{ headerShown: false }}
/>
<Stack.Screen name="Example1" component={Example1} />
<Stack.Screen name="Example2" component={Example2} />
</Stack.Navigator>
);

React Native: Different headers for different screens in Stack Navigator

I am using #react-navigation/stack version ^5.5.1. I am trying to have different headers on different screens in my Stack Navigation. For example, on Master, I want no header, i.e., headerMode="none"; on Home, I want a custom header, and on Details I want a different custom header. How do I achieve this? This is my current code:
const AppStack = () => {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Master" component={ Master } />
<Stack.Screen name="Home" component={ Home } />
<Stack.Screen name="Details" component={ Details } />
</Stack.Navigator>
</NavigationContainer>
)
}
I just figured it out.
First, put headerMode="screen" on the Stack.Navigator. This moves control of the header to each screen. Then use the syntax as shown below for each individual screen.
const AppStack = () => {
return (
<NavigationContainer>
<Stack.Navigator headerMode="screen">
<Stack.Screen name="Master" component={ Master } options={{ headerShown: false }} />
<Stack.Screen name="Home" component={ Home } options={{ headerTitle: props => <MyCustomHeader {...props} /> }}/>
<Stack.Screen name="Details" component={ Details } options={{ headerTitle: props => <MyOtherCustomHeader {...props} /> }}/>
</Stack.Navigator>
</NavigationContainer>
)
}