Search code examples
exporeact-native-navigationbottomtabs

correctly set params in expo bottomtabs


Having a hard time understanding this newest expo bottom tabs

I dont see an initital params on the node_module for the bottomtabs or any params property... has anyone done this? essentially we have component for two bottom tabs and a different effect depending on that tab.

So 1. Can we pass Params into bottomTabs? 2. if so how?

error we get with TS is:

The expected type comes from property 'initialParams' which is declared here on type 'IntrinsicAttributes & RouteConfig<RootTabParamList, "TabThree", TabNavigationState, BottomTabNavigationOptions, BottomTabNavigationEventMap>'

    <BottomTab.Screen
    name="Episodes"
    component={EpisodesScreen}
    initialParams={{
      type: "episodes",
    }}
    options={{
      title: 'Episodes',
      tabBarIcon: ({ color }) => <TabBarFeatherIcon name="headphones" color={color} />,
    }}
    />
    <BottomTab.Screen
    name="TabThree"
    component={EpisodesScreen}
    initialParams={{
      type: "quickGuides",
      displayType: "grid",
    }}

from the node_module::

  import {
  createNavigatorFactory,
  DefaultNavigatorOptions,
  ParamListBase,
  TabActionHelpers,
  TabNavigationState,
  TabRouter,
  TabRouterOptions,
  useNavigationBuilder,
  } from '@react-navigation/native';
  import * as React from 'react';
  import warnOnce from 'warn-once';

import type {
  BottomTabNavigationConfig,
  BottomTabNavigationEventMap,
  BottomTabNavigationOptions,
 } from '../types';
import BottomTabView from '../views/BottomTabView';

type Props = DefaultNavigatorOptions<
ParamListBase,
TabNavigationState<ParamListBase>,
BottomTabNavigationOptions,
BottomTabNavigationEventMap
> &
TabRouterOptions &
BottomTabNavigationConfig;

function BottomTabNavigator({
initialRouteName,
backBehavior,
children,
screenListeners,
screenOptions,
sceneContainerStyle,
...restWithDeprecated
}: Props) {
const {
// @ts-expect-error: lazy is deprecated
lazy,
// @ts-expect-error: tabBarOptions is deprecated
tabBarOptions,
...rest
} = restWithDeprecated;

let defaultScreenOptions: BottomTabNavigationOptions = {};

if (tabBarOptions) {
Object.assign(defaultScreenOptions, {
  tabBarHideOnKeyboard: tabBarOptions.keyboardHidesTabBar,
  tabBarActiveTintColor: tabBarOptions.activeTintColor,
  tabBarInactiveTintColor: tabBarOptions.inactiveTintColor,
  tabBarActiveBackgroundColor: tabBarOptions.activeBackgroundColor,
  tabBarInactiveBackgroundColor: tabBarOptions.inactiveBackgroundColor,
  tabBarAllowFontScaling: tabBarOptions.allowFontScaling,
  tabBarShowLabel: tabBarOptions.showLabel,
  tabBarLabelStyle: tabBarOptions.labelStyle,
  tabBarIconStyle: tabBarOptions.iconStyle,
  tabBarItemStyle: tabBarOptions.tabStyle,
  tabBarLabelPosition:
    tabBarOptions.labelPosition ??
    (tabBarOptions.adaptive === false ? 'below-icon' : undefined),
  tabBarStyle: [
    { display: tabBarOptions.tabBarVisible ? 'none' : 'flex' },
    defaultScreenOptions.tabBarStyle,
  ],
});

(
  Object.keys(defaultScreenOptions) as (keyof BottomTabNavigationOptions)[]
).forEach((key) => {
  if (defaultScreenOptions[key] === undefined) {
    // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
    delete defaultScreenOptions[key];
  }
});

warnOnce(
  tabBarOptions,
  `Bottom Tab Navigator: 'tabBarOptions' is deprecated. Migrate the options to 
'screenOptions' instead.\n\nPlace the following in 'screenOptions' in your code to keep 
current behavior:\n\n${JSON.stringify(
    defaultScreenOptions,
    null,
    2
  )}\n\nSee https://reactnavigation.org/docs/bottom-tab-navigator#options for more 
details.`
);
}

if (typeof lazy === 'boolean') {
defaultScreenOptions.lazy = lazy;

warnOnce(
  true,
  `Bottom Tab Navigator: 'lazy' in props is deprecated. Move it to 'screenOptions' 
   instead.\n\nSee https://reactnavigation.org/docs/bottom-tab-navigator/#lazy for more 
  details.`
   );
  }

const { state, descriptors, navigation, NavigationContent } =
 useNavigationBuilder<
  TabNavigationState<ParamListBase>,
  TabRouterOptions,
  TabActionHelpers<ParamListBase>,
  BottomTabNavigationOptions,
  BottomTabNavigationEventMap
  >(TabRouter, {
  initialRouteName,
  backBehavior,
  children,
  screenListeners,
  screenOptions,
  defaultScreenOptions,
 });

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

export default createNavigatorFactory<
TabNavigationState<ParamListBase>,
BottomTabNavigationOptions,
BottomTabNavigationEventMap,
typeof BottomTabNavigator
>(BottomTabNavigator);

Solution

  • only way i found to get my componenet to render on two different routes from the bottom tabs is to use the useNavigationState

    import { useNavigationState } from "@react-navigation/native"

    made a constant to check the route name and then on use effect we check the case...

      const screenName = useNavigationState((state) => 
      state.routes[state.index].name)
      
      const type = screenName
    
    
     useEffect(() => {
    
      switch (type) {
      case "Episodes": 
        setTitle("Episodes")
        setIsLoading(false)
        break
        case "quickGuides":
        setTitle("Quick Guides")
    
        setIsLoading(false)
        break
        }
      }, [])