title: How to fix 'navigation.state is not defined' in custom react-navigation component?
body: <p>I'm trying to use a custom component (<code>tabBarComponent</code> property) for my React Native app using <code>createMaterialTopTabNavigator</code> from <code>"react-native-tabs"</code>, the component being <code>BottomNavigation</code> from <code>"react-native-paper"</code>.</p>
  
  <p>I have copied nearly all of the code from <a href="https://github.com/react-navigation/material-bottom-tabs" rel="nofollow noreferrer">https://github.com/react-navigation/material-bottom-tabs</a> , as it is the only source I have found for using <code>BottomNavigation</code> as a custom component</p>
  
  <p>I have 3 main pieces of code:
  
    <code>TabNavigator (component)</code></p>
  
  <pre><code>class CustomTabNavigator extends React.Component {
  _getColor = ({ route }) =&gt; {
    const { descriptors } = this.props;
    const descriptor = descriptors[route.key];
    const options = descriptor.options;
  
    if (this.context === 'dark' &amp;&amp; options.tabBarColorDark) {
      return options.tabBarColorDark;
    } else if (options.tabBarColorLight) {
      return options.tabBarColorLight;
    } else {
      return options.tabBarColor;
    }
  };
  
  _getactiveColor = () =&gt; {
    let { activeColor, activeColorLight, activeColorDark } = this.props;
  
    if (this.context === 'dark' &amp;&amp; activeColorDark) {
      return activeColorDark;
    } else if (activeColorLight) {
      return activeColorLight;
    } else {
      return activeColor;
    }
  };
  
  _getInactiveColor = () =&gt; {
    let { inactiveColor, inactiveColorLight, inactiveColorDark } = this.props;
  
    if (this.context === 'dark' &amp;&amp; inactiveColorDark) {
      return inactiveColorDark;
    } else if (inactiveColorLight) {
      return inactiveColorLight;
    } else {
      return inactiveColor;
    }
  };
  
  _getBarStyle = () =&gt; {
    let { barStyle, barStyleLight, barStyleDark } = this.props;
  
    return [barStyle, this.context === 'dark' ? barStyleDark : barStyleLight];
  };
  
  _isVisible() {
    const { navigation, descriptors } = this.props;
    const { state } = navigation;
    const route = state.routes[state.index];
    const options = descriptors[route.key].options;
    return options.tabBarVisible;
  }
  
  _renderIcon = ({
    route,
    focused,
    color,
  }) =&gt; {
    return this.props.renderIcon({ route, focused, tintColor: color });
  };
  
  render() {
    const {
      navigation,
      descriptors,
      ...rest
    } = this.props;
  
    const activeColor = this._getactiveColor();
    const inactiveColor = this._getInactiveColor();
    const barStyle = this._getBarStyle();
  
    const isVisible = this._isVisible();
    const extraStyle =
      isVisible === false
        ? {
            display: 'none',
            position: undefined,
          }
        : null;
  
    return (
      &lt;BottomNavigation
        {...rest}
        activeColor={activeColor}
        inactiveColor={inactiveColor}
        renderIcon={this._renderIcon}
        barStyle={[barStyle, extraStyle]}
        navigationState={navigation.state}
        getColor={this._getColor}
      /&gt;
    )
  }
  }
  </code></pre>
  
  <p>
  
    <code>TabNavigation (navigator)</code></p>
  
  <pre><code>class CustomTabNavigation extends React.Component {
  _renderScene = ({ route }) =&gt; {
    const { screenProps, descriptors } = this.props;
    const descriptor = descriptors[route.key];
    const TabComponent = descriptor.getComponent();
    return (
      &lt;SceneView
        screenProps={screenProps}
        navigation={descriptor.navigation}
        component={TabComponent}
      /&gt;
    );
  };
  
  _renderIcon = ({
    route,
    focused,
    tintColor,
    horizontal = false,
  }) =&gt; {
    const { descriptors } = this.props;
    const descriptor = descriptors[route.key];
    const options = descriptor.options;
  
    if (options.tabBarIcon) {
      return typeof options.tabBarIcon === 'function'
        ? options.tabBarIcon({ focused, tintColor, horizontal })
        : options.tabBarIcon;
    }
  
    return null;
  };
  
  _getLabelText = ({ route }) =&gt; {
    const { descriptors } = this.props;
    const descriptor = descriptors[route.key];
    const options = descriptor.options;
  
    if (options.tabBarLabel) {
      return options.tabBarLabel;
    }
  
    if (typeof options.title === 'string') {
      return options.title;
    }
  
    return route.routeName;
  };
  
  _getAccessibilityLabel = ({ route }) =&gt; {
    const { descriptors } = this.props;
    const descriptor = descriptors[route.key];
    const options = descriptor.options;
  
    if (typeof options.tabBarAccessibilityLabel !== 'undefined') {
      return options.tabBarAccessibilityLabel;
    }
  
    const label = this._getLabelText({ route });
  
    if (typeof label === 'string') {
      const { routes } = this.props.navigation.state;
      return `${label}, tab, ${routes.indexOf(route) + 1} of ${
        routes.length
      }`;
    }
  
    return undefined;
  };
  
  _getTestID = ({ route }) =&gt; {
    const { descriptors } = this.props;
    const descriptor = descriptors[route.key];
    const options = descriptor.options;
  
    return options.tabBarTestID;
  };
  
  _getBadge = ({ route }) =&gt; {
    const { descriptors } = this.props;
    const descriptor = descriptors[route.key];
    const options = descriptor.options;
  
    return options.tabBarBadge;
  };
  
  _makeDefaultHandler = ({
    route,
    navigation,
  }) =&gt; () =&gt; {
    if (navigation.isFocused()) {
      if (route.hasOwnProperty('index') &amp;&amp; route.index &gt; 0) {
        navigation.dispatch(StackActions.popToTop({ key: route.key }));
      } else {
        navigation.emit('refocus');
      }
    } else {
      this._jumpTo(route.routeName);
    }
  };
  
  _handleTabPress = ({ route }) =&gt; {
    this._isTabPress = true;
    Promise.resolve().then(() =&gt; (this._isTabPress = false));
  
    const { descriptors } = this.props;
    const descriptor = descriptors[route.key];
    const { navigation, options } = descriptor;
  
    const defaultHandler = this._makeDefaultHandler({ route, navigation });
  
    if (options.tabBarOnPress) {
      options.tabBarOnPress({ navigation, defaultHandler });
    } else {
      defaultHandler();
    }
  };
  
  _handleIndexChange = index =&gt; {
    if (this._isTabPress) {
      this._isTabPress = false;
      return;
    }
  
    this._jumpTo(this.props.navigation.state.routes[index].routeName);
  };
  
  _jumpTo = routeName =&gt; {
    const { navigation } = this.props;
  
    navigation.dispatch(
      SwitchActions.jumpTo({
        routeName,
        key: navigation.state.key,
      })
    );
  };
  
  _isTabPress = false;
  
  render() {
    const {
      descriptors,
      navigation,
      screenProps,
      navigationConfig,
    } = this.props;
    const { state } = navigation;
    const route = state.routes[state.index];
    const descriptor = descriptors[route.key];
    const options = {
      ...navigationConfig,
      ...descriptor.options,
    };
  
    return (
      &lt;CustomTabNavigator
        {...options}
        getLabelText={this._getLabelText}
        getAccessibilityLabel={this._getAccessibilityLabel}
        getTestID={this._getTestID}
        getBadge={this._getBadge}
        renderIcon={this._renderIcon}
        renderScene={this._renderScene}
        onIndexChange={this._handleIndexChange}
        onTabPress={this._handleTabPress}
        navigation={navigation}
        descriptors={descriptors}
        screenProps={screenProps}
      /&gt;
    );
  }
  }
  </code></pre>
  
  <p>
  
    <code>Main navigation</code></p>
  
  <pre><code>const TabNavigator = createStackNavigator(
  {
    TabsStack: {
      ...,
      {
        ...,
        tabBarComponent: ({ props }) =&gt; &lt;CustomTabNavigation {...props} /&gt;
      })
    },
  }
  );
  </code></pre>
  
  <p></p>
  
  <p>I was expecting to be able to use the <code>swipeEnabled</code> feature (animated transition to and from each screen) from <code>createMaterialTopTabNavigator</code> from "react-navigation", as well as having a better-looking tab bar, but it says that <code>'navigation.state is undefined'</code> in the render function of <code>CustomTabNavigation</code> (line <code>const { state } = navigation;</code>), but I can't see the reason why.</p>