Right now I have the following directory structure:
├── (app)
│ ├── (tabs)
│ │ ├── _layout.tsx
│ │ ├── chat
│ │ │ ├── _layout.tsx
│ │ │ └── index.tsx
│ │ ├── overview
│ │ │ ├── _layout.tsx
│ │ │ └── index.tsx
│ │ └── settings
│ │ ├── _layout.tsx
│ │ └── index.tsx
inside a src directory in a project using expo router v2.
(tabs)/_layout.tsx:
import {CustomTopTabs} from "@components/ui/layouts/CustomTopTabs";
export default function Layout() {
return (
<CustomTopTabs />
)
}
CustomTopTabs.tsx:
// imports
const Tab= createMaterialTopTabNavigator();
function CustomTopTabNavigator() {
return (
<Tab.Navigator
initialRouteName='overview'
screenOptions={({route}) =>
// screen options
>
<Tab.Screen name="settings" component={Settings} />
<Tab.Screen name="overview" component={Overview} />
<Tab.Screen name="chat" component={Chat} />
</Tab.Navigator>
)
}
export const CustomTopTabs = withLayoutContext(CustomTopTabNavigator);
// styles
chat/_layout.tsx:
import {Slot} from "expo-router";
import {Group} from "@ui/layout";
export default function Layout() {
return (
<Group style={{backgroundColor: 'black'}}>
<Slot />
</Group>
);
}
chat/index.tsx:
import {Text} from "@ui";
import {View} from "react-native";
export default function Page() {
return <View>
<Text.Display padBottom={8}>Chat</Text.Display>
</View>
};
But the layout in the child chat directory is not being respected. Is the use of a custom navigator preventing the nesting of navigation?
I ended up solving this by nesting a <Stack.Navigator>
within the chat/index.tsx
route.
chat/index.tsx:
import {Text, View} from "react-native";
import {Link, useNavigation} from "expo-router";
import {NavigationProp, ParamListBase} from "@react-navigation/native";
import {createNativeStackNavigator} from "@react-navigation/native-stack";
import One from "path/to/src/(app)/(tabs)/chat/one";
function Index() {
const navigation: NavigationProp<ParamListBase> = useNavigation();
const handleOnPress = e => {
e.preventDefault();
navigation.navigate('one');
};
return <View>
<Text>Chat</Text>
<Text><Link href="/chat/one" onPress={handleOnPress}>One</Link></Text>
</View>
};
export default function Page() {
const Stack = createNativeStackNavigator();
return (
<Stack.Navigator
screenOptions={{
headerShown: false
}}
>
<Stack.Screen name="index" component={Index}/>
<Stack.Screen name="one" component={One}/>
</Stack.Navigator>
);
}
chat/_layout.tsx:
export default function Layout() {
}
chat/one/_layout.tsx:
export default function Layout() {
}
chat/one/index.tsx:
import {View, Text} from "react-native";
import {Link, useNavigation} from "expo-router";
export default function Page() {
const navigator = useNavigation();
const handleOnPress = e => {
e.preventDefault();
navigator.goBack();
};
return <View>
<Text>One</Text>
<Text><Link href="/chat" onPress={handleOnPress}>Back</Link></Text>
</View>;
}