Skip to content

createMaterialBottomTabNavigator return type is any #4671

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
Michota opened this issue Apr 9, 2025 · 1 comment
Open

createMaterialBottomTabNavigator return type is any #4671

Michota opened this issue Apr 9, 2025 · 1 comment
Labels

Comments

@Michota
Copy link

Michota commented Apr 9, 2025

Current behaviour

Using createMaterialBottomTabNavigator from "react-native-paper/react-navigation" returns fully functional Tab navigator, but with any type, making it impossible to work with using Typescript.

Expected behaviour

It should return something which will allow Intelisense to work as it should: e.g. it should instruct user to use <Tabs.Navigator> or to use component prop in <Tabs.Screen/>

How to reproduce?

import TabBarIcon from "@/src/components/TabBarIcon";
import { createMaterialBottomTabNavigator } from "react-native-paper/react-navigation";
import MessagesRoute from "./messages";
import Notifications from "./notifications";

const Tabs = createMaterialBottomTabNavigator();

export default function CommunicationLayout() {
  return (
    <Tabs.Navigator>
      <Tabs.Screen
        component={MessagesRoute}
        name="messages"
        options={{ title: "Messages", tabBarIcon: () => <TabBarIcon iconName="mail" /> }}
      />
      <Tabs.Screen
        component={Notifications}
        name="notifications"
        options={{ title: "Notifications", tabBarLabel: () => undefined }}
      />
    </Tabs.Navigator>
  );
}

Preview

Image

What have you tried so far?

There is no easy solution for that. I tried installing react-navigation and importing types, but it didn't help.

Your Environment

software version
ios x
android 13
react-native latest
react-native-paper latest
node 22.13.1
npm or yarn pnpm - latest
expo sdk 53
@Michota Michota added the bug label Apr 9, 2025
@RainPlays09
Copy link

I created a Pull Request all about this issue but it is not merge. Until PR is not merge, you can use my workaround. Just create a .tsx file and paste this code:

import {
  createNavigatorFactory,
  DefaultNavigatorOptions,
  NavigatorTypeBagBase,
  ParamListBase,
  StaticConfig,
  TabActionHelpers,
  TabNavigationState,
  TabRouter,
  TabRouterOptions,
  TypedNavigator,
  useNavigationBuilder,
} from "@react-navigation/native";
import {
  MaterialBottomTabNavigationEventMap,
  MaterialBottomTabNavigationOptions,
  MaterialBottomTabView,
} from "react-native-paper/react-navigation";
import { BottomNavigation } from "react-native-paper";

import { withLayoutContext } from "expo-router";

type MaterialBottomTabNavigationConfig = Partial<
  Omit<
    React.ComponentProps<typeof BottomNavigation>,
    | "navigationState"
    | "onIndexChange"
    | "onTabPress"
    | "onTabLongPress"
    | "renderScene"
    | "renderLabel"
    | "renderIcon"
    | "getAccessibilityLabel"
    | "getBadge"
    | "getColor"
    | "getLabelText"
    | "getTestID"
    | "getLazy"
  >
>;

export type MaterialBottomTabNavigatorProps = DefaultNavigatorOptions<
  ParamListBase,
  undefined,
  TabNavigationState<ParamListBase>,
  MaterialBottomTabNavigationOptions,
  MaterialBottomTabNavigationEventMap,
  typeof MaterialBottomTabView
> &
  TabRouterOptions &
  MaterialBottomTabNavigationConfig;

function MaterialBottomTabNavigator({
  id,
  initialRouteName,
  backBehavior,
  children,
  screenListeners,
  screenOptions,
  ...rest
}: MaterialBottomTabNavigatorProps) {
  const { state, descriptors, navigation, NavigationContent } =
    useNavigationBuilder<
      TabNavigationState<ParamListBase>,
      TabRouterOptions,
      TabActionHelpers<ParamListBase>,
      MaterialBottomTabNavigationOptions,
      MaterialBottomTabNavigationEventMap
    >(TabRouter, {
      id,
      initialRouteName,
      backBehavior,
      children,
      screenListeners,
      screenOptions,
    });

  return (
    <NavigationContent>
      <MaterialBottomTabView
        {...rest}
        state={state}
        navigation={navigation}
        descriptors={descriptors}
      />
    </NavigationContent>
  );
}

function createMaterialBottomTabs<
  const ParamList extends ParamListBase,
  const NavigatorID extends string | undefined,
  const TypeBag extends NavigatorTypeBagBase = {
    ParamList: ParamList;
    NavigatorID: NavigatorID;
    State: TabNavigationState<ParamList>;
    ScreenOptions: MaterialBottomTabNavigationOptions;
    EventMap: MaterialBottomTabNavigationEventMap;
    NavigationList: {
      [RouteName in keyof ParamList]: MaterialBottomTabNavigatorProps;
    };
    Navigator: typeof MaterialBottomTabNavigator;
  },
  const Config extends StaticConfig<TypeBag> = StaticConfig<TypeBag>
>(config?: Config): TypedNavigator<TypeBag, Config> {
  return createNavigatorFactory(MaterialBottomTabNavigator)(config);
}

export default createMaterialBottomTabs;

If you're using expo, you can use the withContextLayout from expo-router:

const { Navigator } = createMaterialBottomTabs();

export const MaterialBottomTabs = withLayoutContext<
  MaterialBottomTabNavigationOptions,
  typeof Navigator,
  TabNavigationState<ParamListBase>,
  MaterialBottomTabNavigationEventMap
>(Navigator);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants