Reputation: 1717
I am trying the new Expo-Router with a complex nesting navigation, currently i'm trying to display a screen with a presentation of modal, which itself is a part of a bottom tab navigation, but it is not presenting as a modal but as a simple stack screen:
Project layout:
app/
_layout.tsx
index.tsx
(main)/
_layout.tsx
(tabs)/
_layout.tsx
home/
create/
profile/
search/
notifications/
(main)/(tabs)/_layout.tsx:
import {Tabs} from "expo-router/tabs";
export default function Layout() {
return (
<Tabs>
<Tabs.Screen name='home'/>
<Tabs.Screen name='search'/>
<Tabs.Screen name='create'/> // should be presented as modal
<Tabs.Screen name='notifications'/>
<Tabs.Screen name='profile'/>
</Tabs>
)
}
(main)/(tabs)/create/_layout.tsx
import {Stack} from "expo-router/stack";
export default function Layout() {
return (
<Stack>
<Stack.Screen name="index" options={{presentation: "modal"}}/>
</Stack>
)
}
The create
page should be a stack with presentation set to modal in order for it to work/render as a modal screen right?
Reproducible repo:- https://github.com/theartificialguy/Threads
Upvotes: 5
Views: 12299
Reputation: 147
I think the easiest solution is to change the href
of the create tab-button to point to the url of the create page:
<Tabs.Screen name='create' options={{ href: "create" }} />
Upvotes: -2
Reputation: 12808
You can do this systematically by using the navigation.getState()
method
Here's an example of using it to hide the bottom bar anytime the active screen has nested navigation
<Tabs
screenOptions={({ route, navigation }) => {
const state = navigation.getState();
const hasNestedNavigation = state.routes[state.index].state?.index > 0; // if the current state's route has a state, and its not the index of that route, then we've detected nested navigation
navigation
return {
tabBarStyle: {
display: hasNestedNavigation ? 'none' : undefined, // hide for all nested navigation screens
},
};
}}
>
{/** ... */}
</Tabs>
This answer builds on the following resources:
You can extend this answer to customize when you do or do not want the bottom bar to display without limit given the navigation state
, so any usecase you have should be covered.
initialRouteName
is required on each stack with expo-router
Otherwise, not only will this solution be broken on refreshes, but more importantly, for all situations with expo-router
deeplinks and refreshes will not display the back button on your stack screens.
For example
export const unstable_settings = {
initialRouteName: '/index',
};
ref: https://docs.expo.dev/router/advanced/router-settings/
Upvotes: 1
Reputation: 1717
I was able to solve it using the listener
prop in Tabs.Screen
.
Reference: https://stackoverflow.com/a/68900301/11685381
Upvotes: 2