Skip to content
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

Bottom Tab with expo-router 3 #4346

Open
silencer07 opened this issue Mar 19, 2024 · 6 comments
Open

Bottom Tab with expo-router 3 #4346

silencer07 opened this issue Mar 19, 2024 · 6 comments
Labels
question Question related to the library, not an issue

Comments

@silencer07
Copy link

silencer07 commented Mar 19, 2024

Scouring from net I was able to have expo-router use react-native-paper bottom tabs. However screenOptions and tabBarIcon is having error in typescript.

import {
  createMaterialBottomTabNavigator,
  MaterialBottomTabNavigationOptions,
  MaterialBottomTabNavigationEventMap,
} from "react-native-paper/react-navigation";

import { TabNavigationState, ParamListBase } from "@react-navigation/native";

import { withLayoutContext } from "expo-router";
import {
  BottomTabNavigationEventMap,
  BottomTabNavigationOptions,
} from "@react-navigation/bottom-tabs";

const BottomTabNavigator = createMaterialBottomTabNavigator().Navigator;

export const MaterialBottomTabs = withLayoutContext<
  MaterialBottomTabNavigationOptions | BottomTabNavigationOptions,
  typeof BottomTabNavigator,
  TabNavigationState<ParamListBase>,
  MaterialBottomTabNavigationEventMap | BottomTabNavigationEventMap
>(BottomTabNavigator);

What is the proper way of integrating expo-router to react-native-paper's bottom tab without having to resolve to using any on screenOptions and manually typing the tabBarIcon option

@silencer07 silencer07 added the question Question related to the library, not an issue label Mar 19, 2024
@silencer07
Copy link
Author

Found out the above does not work because it removes the header of the containing root stack!

@Shadic78
Copy link

Shadic78 commented Aug 6, 2024

@silencer07 Did you find a workaround?

@silencer07
Copy link
Author

silencer07 commented Aug 8, 2024

@Shadic78 unfortunately no. I just used the expo tab for my pet project.

If you can call this a workaround basically I did this: https://callstack.github.io/react-native-paper/docs/guides/theming-with-react-navigation/

 import {
   DarkTheme as NavigationDarkTheme,
   DefaultTheme as NavigationDefaultTheme,
 } from "@react-navigation/native";
 import merge from "deepmerge";
 import {
   adaptNavigationTheme,
   MD3DarkTheme,
   MD3LightTheme,
   MD3Theme,
 } from "react-native-paper";
 import { NavigationTheme } from "react-native-paper/lib/typescript/types";
 
 const { LightTheme, DarkTheme } = adaptNavigationTheme({
   reactNavigationLight: NavigationDefaultTheme,
   reactNavigationDark: NavigationDarkTheme,
 });
 
 // ..ommitted for brevity
 const colors = {...}
 
 const rnPaperLightTheme = { ...MD3LightTheme };
 rnPaperLightTheme.colors.onSurface = colors.textColor;
 rnPaperLightTheme.colors.onPrimary = "black";
 rnPaperLightTheme.colors.onSurfaceVariant = "#475569";
 rnPaperLightTheme.colors.surfaceVariant = colors.bgColor;
 
 const navigationLightTheme = { ...LightTheme };
 navigationLightTheme.colors.background = colors.bgColor; // bg of the content child
 navigationLightTheme.colors.card = colors.bgColor; // header and tab colors
 navigationLightTheme.colors.primary = colors.textColor; // active tab color
 navigationLightTheme.colors.text = colors.textColor; // header text
 
 export const CombinedDefaultTheme: MD3Theme & NavigationTheme = merge(
   rnPaperLightTheme,
   navigationLightTheme,
 );
 
 export const CombinedDarkTheme: MD3Theme & NavigationTheme = merge(
   MD3DarkTheme,
   DarkTheme,
 );

Then on your root _layout.tsx

  return (
        <PaperProvider theme={CombinedDefaultTheme}>
          <ThemeProvider value={CombinedDefaultTheme}>
            <GestureHandlerRootView style={{ flex: 1 }}>
                  <Slot /> // or you can use the old-school react navigation way. haven't tried it
            </GestureHandlerRootView>
          </ThemeProvider>
        </PaperProvider>
  );

@TamasSzigeti
Copy link

Not strictly the same issue but this might help some peeps landing here

@RainPlays09
Copy link

RainPlays09 commented Dec 22, 2024

I tried to fix the Props of BottomNavigation in react-native-paper/react-navigation. I encounter some error in creating. (sorry for wrong grammars)

  • Warning: A props object containing a "key" prop is being spread into JSX:
    let props = {key: someKey, route: ..., borderless: ..., centered: ..., rippleColor: ..., onPress: ..., onLongPress: ..., testID: ..., accessibilityLabel: ..., accessibilityRole: ..., accessibilityState: ..., style: ..., children: ...}; <Touchable {...props} /> React keys must be passed directly to JSX without using spread: let props = {route: ..., borderless: ..., centered: ..., rippleColor: ..., onPress: ..., onLongPress: ..., testID: ..., accessibilityLabel: ..., accessibilityRole: ..., accessibilityState: ..., style: ..., children: ...}; <Touchable key={someKey} {...props} />. I think this error occurs at BottomNavigation.Bar

I hope this will help:

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

const { Navigator } = createMaterialBottomTabs();

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

export default MaterialBottomTabs;

@SleeplessByte
Copy link
Contributor

See: #4496 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Question related to the library, not an issue
Projects
None yet
Development

No branches or pull requests

5 participants