I’m newbie React Native developer, and I was struggling to encounter some solution for the topic. And after some hours spent researching on forums (Reddit, stack overflow, and Github issues), I found a suitable solution for me.
I’m posting this in hopes to help other persons that are faced with the same problem.
I’m using:
- Expo 51.0.24 SDK;
- Expo-Router 3.5.20;
Basically, my project is structured in this way:
app
_layout.tsx
modal.tsx
(auth)
(root)
_layout.tsx (where is my Tabs)
(home)
add.tsx --> just return an empty <View />
...other groups
In my app/_layout.tsx
I have the following code:
<Stack screenOptions={{ headerShown: false }}>
<Stack.Screen name="(auth)" options={{ headerShown: false }} />
<Stack.Screen name="(root)" options={{ headerShown: false }} />
<Stack.Screen
name="modal"
options={{
headerShown: false,
presentation: "transparentModal",
animation: "fade_from_bottom",
contentStyle: {
backgroundColor: "rgba(0, 0, 0, 0.5)", --> shadow color when modal appears
justifyContent: "flex-end", --> to the content appears on the bottom of the screen
},
}}
/>
<Stack.Screen name="+not-found" />
</Stack>
Basically, define root routes of the app and on Modal <Stack.Screen>
I define on options the presentation
.
Now here is the trick to be possible my modal appear on any screen and be “invoked” from my <Tabs>
.
In my app/(root)/_layout.tsx
I have the following code:
function HomeIcon({ color, focused }: { color: string; focused: boolean }) {
return <TabBarIcon name={focused ? "home" : "home-outline"} color={color} />;
}
function AddIcon({ color, focused }: { color: string; focused: boolean }) {
return (
<TouchableOpacity
style={{
backgroundColor: color,
borderRadius: 100,
alignItems: "center",
justifyContent: "center",
width: 56,
height: 56,
}}
onPress={() => router.push("/modal")}
>
<Ionicons name="add" size={32} color={focused ? color : "white"} />
</TouchableOpacity>
);
}
export default function AppRootLayout() {
return (
<Tabs>
<Tabs.Screen
name="(home)"
options={{
title: "Home",
tabBarIcon: HomeIcon,
headerShown: false,
href: "/(home)",
tabBarShowLabel: false,
}}
/>
<Tabs.Screen
name="add"
options={{
tabBarIcon: AddIcon,
headerShown: false,
tabBarShowLabel: false,
}}
/>
// ...other tabs
</Tabs>
);
}
Basically, what I did was define my Add Button on my Tab, pointing the prop name (that inform the nested route for expo) to add.tsx
(that only return an empty <View />
), and when the action onPress
is triggered on my button, I use router.push("/your_root_route_name")
to show modal.
Here is the video showing my solution working:
https://gofile.io/d/RB93JF
I hope that help someone :).
1