Njoroge Brian
Njoroge Brian

Reputation: 307

How to nest expo tabs inside material top tabs

I'm new to react native, started just when expo tabs became official (I'm not even sure). I have top tabs navigation, created with material to tabs since current expo Tabs only supports bottom navigation.

I want to have bottom tabs nested in each top tab, so let's say Social top tab has its own individual bottom tabs, in the screenshot above, you can see that Social top tab has bottom tabs cats and dogs but they only show when in social bottom tabs which should not be showing.

I know I'm getting the file routing wrong (I guess). In the main toptabs layout file, I have top material tabs defined and for each Tab Screen, in this case the Social tab screen, I'm rendering AppLayout which renders the tabs inside social directory that is cats and dogs.

This is the main layout file inside (toptabs), it renders the top tabs components, the first Tab.Screen renders the AppLayout which renders the bottom tabs inside the social directory inside the toptabs.

import FontAwesome from "@expo/vector-icons/FontAwesome";
import {
  useColorScheme
} from "react-native";
import Colors from "../../constants/Colors";
import {
  createMaterialTopTabNavigator
} from "@react-navigation/material-top-tabs";
import MarketplaceHome from "./marketplace";
import ChatHome from "./chat";
import AppLayout from "./social/(tabs)/_layout";

const Tab = createMaterialTopTabNavigator();

function TabBarIcon(props: {
  name: React.ComponentProps < typeof FontAwesome > ["name"];
  color: string;
}) {
  return <FontAwesome size = {
    28
  }
  style = {
    {
      marginBottom: -3
    }
  } { ...props
  }
  />;
}

export default function TabLayout() {
  const colorScheme = useColorScheme();

  return ( <
    Tab.Navigator screenOptions = {
      {
        tabBarActiveTintColor: Colors[colorScheme ? ? "light"].tint,
      }
    } >
    <
    Tab.Screen name = "Social"
    component = {
      AppLayout
    }
    options = {
      {
        tabBarIcon: ({
          color
        }) => < TabBarIcon name = "home"
        color = {
          color
        }
        />,
      }
    }
    /> <
    Tab.Screen name = "Marketplace"
    component = {
      MarketplaceHome
    }
    options = {
      {
        tabBarIcon: ({
          color
        }) => < TabBarIcon name = "feed"
        color = {
          color
        }
        />,
      }
    }
    /> <
    Tab.Screen name = "Chat"
    component = {
      ChatHome
    }
    options = {
      {
        tabBarIcon: ({
          color
        }) => < TabBarIcon name = "female"
        color = {
          color
        }
        />,
      }
    }
    /> <
    /Tab.Navigator>
  );
}

This is the AppLayout inside social directory inside toptabs, ideally, cats and dogs should render inside Social top tab, the problem is even the other directories are rendering as bottom tabs, that is chat, marketplace and social, and now cats and dogs is showing only in social bottom tabs inside social top tab

import {
  Tabs
} from "expo-router";
import {
  Text
} from "react-native";

export default function AppLayout() {
  return ( <
    Tabs screenOptions = {
      {
        headerShown: false,
      }
    } >
    <
    Tabs.Screen name = "cats"
    options = {
      {
        title: "Cats",
        tabBarIcon: () => < Text > 🐱 < /Text>,
      }
    }
    /> <
    Tabs.Screen name = "dogs"
    options = {
      {
        title: "Dogs",
        tabBarIcon: () => < Text > 🐶 < /Text>,
      }
    }
    /> <
    /Tabs>
  );
}

Can someone please explain the correct routing file structure for achieving this. Top tabs showing with bottom tabs but only inside social bottom tab which should not be showingHere's the file structure

Upvotes: 1

Views: 890

Answers (1)

Jimmy Obonyo Abor
Jimmy Obonyo Abor

Reputation: 7885

Heres a blog post that shows how to implement it with expo router :

// app/(top-tabs)/_layout.tsx
import {
  MaterialTopTabNavigationEventMap,
  MaterialTopTabNavigationOptions,
  createMaterialTopTabNavigator,
} from "@react-navigation/material-top-tabs";
import { withLayoutContext } from "expo-router";
import { ParamListBase, TabNavigationState } from "@react-navigation/native";

const { Navigator } = createMaterialTopTabNavigator();

export const MaterialTopTabs = withLayoutContext<
  MaterialTopTabNavigationOptions,
  typeof Navigator,
  TabNavigationState<ParamListBase>,
  MaterialTopTabNavigationEventMap
>(Navigator);

export default function TabLayout() {
  return (
    <MaterialTopTabs>
      <MaterialTopTabs.Screen name="index" options={{ title: "Tab One" }} />
      <MaterialTopTabs.Screen name="two" options={{ title: "Tab Two" }} />
    </MaterialTopTabs>
  );
}

Upvotes: -1

Related Questions