Nested navigation with custom navigator breaks expo router

146 Views Asked by At

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?

1

There are 1 best solutions below

0
On BEST ANSWER

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>;
}