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
Related
I have my App stack with Tab navigation and I want to add some more screens to my settings page below is my App.js page how can I do it
App.js
I need to add to make a SettingsStack for this below page
Settings.js
Create a function (for eg: 'TabNavigation') which returns tab navigator component then try putting tab navigator inside stack like below example
import Profile from '../screens/settings/Profile';
import ManageRooms from '../screens/settings/ManageRooms';
....
const TabNavigation = () => {
<Tab.Navigator
.....
</<Tab.Navigator>
}
....
<NavigationContainer>
{authState.isAuthenticated ? (
<Stack.Navigator
initialRouteName="Tabs"
screenOptions={{
headerShown: false,
}}>
<Stack.Screen name="Tabs" component={TabNavigation} />
<Stack.Screen
key={'Profile'}
name={'Profile'}
component={Profile}
/>
<Stack.Screen
key={'ManageRooms'}
name={'ManageRooms'}
component={ManageRooms}
/>
</Stack.Navigator>) : (
<Stack.Navigator
screenOptions={{
header: () => {},
}}>
<Stack.Screen name="SignIn" component={SignIn} />
<Stack.Screen name="SignUp" component={SignUp} />
</Stack.Navigator>
)}
</NavigationContainer>
....
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>
);
I set up the createStackNavigator as follows:
export default function TabOneScreen() {
return (
<NavigationContainer independent={true} >
<Stack.Navigator initialRouteName="Screen1">
<Stack.Screen name="Screen1" component={Screen1} />
<Stack.Screen name="Screen2" component={Screen2} />
</Stack.Navigator>
</NavigationContainer>
);
}
There is a button on Screen1 that navigates to Screen2:
onPress={() => navigation.navigate('Screen2')}
However, when this navigates, I don't see the button to go back to Screen1. How do I enable this? Thanks!
Because you navigate to another page, you don't push another on top of the stack.
To do that you need to use
onPress={() => navigation.push('Screen2')}
EDIT
With a stack in a stack, you can try to pass parent navigation to props like
export default function TabOneScreen({navigation}) {
return (
<NavigationContainer independent={true} >
<Stack.Navigator initialRouteName="Screen1">
<Stack.Screen parentNavigation={navigation} name="Screen1" component={Screen1} />
<Stack.Screen name="Screen2" component={Screen2} />
</Stack.Navigator>
</NavigationContainer>
);
}
Then
this.props.parentNavigation.push('Screen2')
I found this:
https://reactnavigation.org/docs/nesting-navigators/
Add this prop to your parent stack navigator: headerShown: false
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>
)
}
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.