You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Gorhom底部弹窗中使用React Navigation向Tab栈推送路由问题

问题描述

在React Native应用中,使用React Navigation处理路由、Gorhom Bottom Sheet实现底部弹窗交互,当前配置如下:

import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
import { NavigationContainer } from "@react-navigation/native";
import { PLScreenRoute } from "navigation/screenRoutes";
import FeedTab from "navigation/tabs/feed/FeedTab";
import { BottomSheetModalProvider } from "@gorhom/bottom-sheet";

type NavigationWrapperProps = {
  setAppIsReady: () => void;
};

const NavigationWrapper = ({ setAppIsReady }: NavigationWrapperProps) => {
  const Tab = createBottomTabNavigator();
  
  return (
    <NavigationContainer
    >
      {/*modal provider is here so we can do routing inside of bottom sheets*/}
      <BottomSheetModalProvider>
        <Tab.Navigator
        >
          <Tab.Screen name={PLScreenRoute.FEED_ROOT} component={FeedTab} />
        </Tab.Navigator>
      </BottomSheetModalProvider>
    </NavigationContainer>
  );
};

export default NavigationWrapper;

FeedTab示例代码

import { PLScreenRoute } from "navigation/screenRoutes";
import FeedScreen from "screens/feed/feed/FeedScreen";
import FeedHeader from "screens/feed/feed/FeedHeader";
import { createNativeStackNavigator } from "@react-navigation/native-stack";

export const FeedTabStack = createNativeStackNavigator();

const FeedTab = () => {
  return (
    <FeedTabStack.Navigator initialRouteName={PLScreenRoute.FEED}>
      <FeedTabStack.Screen
        name={PLScreenRoute.FEED}
        component={FeedScreen}
        options={{
          header: () => <FeedHeader />,
        }}
      />
    </FeedTabStack.Navigator>
  );
};

export default FeedTab;

问题详情

在底部弹窗外调用以下代码正常:

import { useNavigation } from "@react-navigation/native";
import { PLScreenRoute } from "navigation/screenRoutes";

const navigator = useNavigation();
const navigate = () => navigator.push(PLScreenRoute.FEED)

但在底部弹窗内调用会崩溃,报错:TypeError: navigator.push is not a function (it is undefined), js engine: hermes

改用navigator.navigate()可正常工作,但需要push()的重复入栈功能,而非navigate()的路由切换逻辑(若路由已存在则直接切换到对应栈)。


解决方案

原因分析

底部弹窗内通过useNavigation()获取的是TabNavigator的导航器实例,而Tab导航器本身没有push()方法,只有navigate();弹窗之外的组件处于StackNavigator的上下文内,拿到的是Stack导航器实例,因此push()可用。

具体解决方法

方法1:明确指定Stack导航器类型

在FeedTab文件中定义栈导航器的类型,然后在弹窗组件中通过泛型获取对应导航器:

  1. 在FeedTab.tsx中添加类型定义:
// FeedTab.tsx
import { NativeStackNavigationProp } from "@react-navigation/native-stack";
import { PLScreenRoute } from "navigation/screenRoutes";

// 定义FeedTab栈的导航类型
export type FeedTabNavigationProp = NativeStackNavigationProp<
  typeof FeedTabStack.navigator,
  PLScreenRoute.FEED
>;
  1. 在弹窗组件中使用泛型版useNavigation():
import { useNavigation } from "@react-navigation/native";
import { FeedTabNavigationProp } from "navigation/tabs/feed/FeedTab";
import { PLScreenRoute } from "navigation/screenRoutes";

const navigator = useNavigation<FeedTabNavigationProp>();
const navigate = () => navigator.push(PLScreenRoute.FEED);

方法2:调整BottomSheetModalProvider层级

将BottomSheetModalProvider从TabNavigator外层移到每个Tab的StackNavigator内部,让弹窗处于Stack导航器的上下文:

  1. 修改NavigationWrapper.tsx:
// NavigationWrapper.tsx
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
import { NavigationContainer } from "@react-navigation/native";
import { PLScreenRoute } from "navigation/screenRoutes";
import FeedTab from "navigation/tabs/feed/FeedTab";

type NavigationWrapperProps = {
  setAppIsReady: () => void;
};

const NavigationWrapper = ({ setAppIsReady }: NavigationWrapperProps) => {
  const Tab = createBottomTabNavigator();
  
  return (
    <NavigationContainer>
      <Tab.Navigator>
        <Tab.Screen name={PLScreenRoute.FEED_ROOT} component={FeedTab} />
      </Tab.Navigator>
    </NavigationContainer>
  );
};

export default NavigationWrapper;
  1. 修改FeedTab.tsx,将Provider包裹StackNavigator:
// FeedTab.tsx
import { PLScreenRoute } from "navigation/screenRoutes";
import FeedScreen from "screens/feed/feed/FeedScreen";
import FeedHeader from "screens/feed/feed/FeedHeader";
import { createNativeStackNavigator } from "@react-navigation/native-stack";
import { BottomSheetModalProvider } from "@gorhom/bottom-sheet";

export const FeedTabStack = createNativeStackNavigator();

const FeedTab = () => {
  return (
    <BottomSheetModalProvider>
      <FeedTabStack.Navigator initialRouteName={PLScreenRoute.FEED}>
        <FeedTabStack.Screen
          name={PLScreenRoute.FEED}
          component={FeedScreen}
          options={{
            header: () => <FeedHeader />,
          }}
        />
      </FeedTabStack.Navigator>
    </BottomSheetModalProvider>
  );
};

export default FeedTab;

方法3:通过getParent()获取Stack导航器(不推荐)

若不想调整组件层级,可尝试从Tab导航器获取父级Stack导航器,但该方式依赖路由层级结构,后续变更易出问题:

import { useNavigation } from "@react-navigation/native";
import { FeedTabNavigationProp } from "navigation/tabs/feed/FeedTab";
import { PLScreenRoute } from "navigation/screenRoutes";

const navigator = useNavigation();
const stackNavigator = navigator.getParent<FeedTabNavigationProp>();
const navigate = () => stackNavigator?.push(PLScreenRoute.FEED);

内容的提问来源于stack exchange,提问作者Malice

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 20:24:57