按下选项卡按钮时强制显示在initialRouteName中定义的屏幕

Jon*_*Jon 1 react-native react-navigation react-navigation-stack react-navigation-bottom-tab

我的底部选项卡导航有问题。这是屏幕结构:

  • 主选项卡:
    • 选项卡A
      • 屏幕A1
    • 标签B
      • 屏幕B1
      • 屏幕B2

我可以从屏幕 A1 导航到屏幕 B2(更改选项卡)。我可以从屏幕 B1 导航到屏幕 B2。

这是示例代码:

import React from "react";
import { StyleSheet, View, Text, Button } from "react-native";
import { NavigationContainer } from "@react-navigation/native";
import { createStackNavigator } from "@react-navigation/stack";
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";

const Tab = createBottomTabNavigator();
const Stack = createStackNavigator();

const TabAScreen1 = ({ route, navigation }) => {
  return (
    <View>
      <Text>Tab A screen 1</Text>
      <Button
        title="Go to tab B screen 2"
        onPress={() => {
          navigation.navigate("TabBStack", { screen: "TabBScreen2" });
        }}
      />
    </View>
  );
};
const TabBScreen1 = ({ route, navigation }) => {
  return (
    <View>
      <Text>Tab B screen 1</Text>
      <Button
        title="Go to tab B screen 2"
        onPress={() => {
          navigation.navigate("TabBScreen2");
        }}
      />
    </View>
  );
};
const TabBScreen2 = ({ route, navigation }) => {
  return (
    <View>
      <Text>Tab B screen 2</Text>
    </View>
  );
};
function TabBStack() {
  return (
    <Stack.Navigator initialRouteName="TabBScreen1" screenOptions={{ headerShown: false }}>
      <Stack.Screen name="TabBScreen1" component={TabBScreen1}/>
      <Stack.Screen name="TabBScreen2" component={TabBScreen2}/>
    </Stack.Navigator>
  );
}
function MainTab() {
  return (
    <Tab.Navigator screenOptions={{ headerShown: false }}>
      <Tab.Screen name="TabAScreen1" component={TabAScreen1}/>
      <Tab.Screen name="TabBStack" component={TabBStack}/>
    </Tab.Navigator>
  );
};

const App = props => {
  const navigationRef = useRef();

  return (
    <NavigationContainer>
      <MainTab/>
    </NavigationContainer>
  );
};

const styles = StyleSheet.create({});

export default App;
Run Code Online (Sandbox Code Playgroud)

导航包:

"@react-navigation/bottom-tabs": "^6.2.0",
"@react-navigation/native": "^6.0.8",
"@react-navigation/stack": "^6.1.1",
Run Code Online (Sandbox Code Playgroud)

一开始,如果我使用底部选项卡按钮导航到选项卡 B,则会加载屏幕 B1。然后我可以从屏幕 B1 或屏幕 A1 导航到屏幕 B2。在屏幕 B2 中,如果我点击选项卡 B 底部选项卡按钮,则会弹出屏幕 B2 并显示屏幕 B1。这是预期的行为。

问题就出在这个。一开始,如果我从屏幕 A1 导航到屏幕 B2,则会加载屏幕 B2。此时,我根本无法导航到屏幕 B1。如果我点击选项卡 B 底部选项卡按钮,则不会发生任何情况,即使设置initialRouteName为。我认为在这种情况下,堆栈中的第一个屏幕是 B2。TabBStackTabBScreen1

是否可以弹出 B2(或堆栈中的所有屏幕)并按下 B1 点击底部选项卡按钮?我了解听众,但我不知道如何实现这种行为。

function MainTab() {
  return (
    <Tab.Navigator screenOptions={{ headerShown: false }}>
      <Tab.Screen name="TabAScreen1" component={TabAScreen1}/>
      <Tab.Screen name="TabBStack" component={TabBStack}
        listeners={({ navigation }) => ({
          tabPress: (e) => {
            console.log("Tab B pressed");
            // If current route is not Screen B1, then pop all and push Screen B1
          },
        })}
      />
    </Tab.Navigator>
  );
};
Run Code Online (Sandbox Code Playgroud)

Dav*_*olz 5

仅当您最初在堆栈 A 中加载应用程序且之前从未访问过堆栈 B 时,才会发生这种情况。这会导致初始路由TabBStack无法挂载!

TabBStack如果您随后导航到from堆栈内的嵌套屏幕TabAScreen1,则默认路由重置功能将不起作用。该框架仅挂载TabBScreen2,但不挂载该特定选项卡中指定的初始路由。

如果我们执行以下操作:

  1. 加载应用程序:默认屏幕是TabAScreen1
  2. 转到TabBStack使用底部选项卡导航。
  3. 回到TabAScreen1.
  4. 单击Go to tab B screen 2按钮
  5. TabBStack底部标签按钮

您会注意到它现在成功重置了路线。这是大多数应用程序中使用的默认行为。

我们如何解决这个问题?

我们有运气。该框架允许我们通过使用初始属性以非常方便的方式做到这一点。

默认情况下,当您在嵌套导航器中导航屏幕时,指定的屏幕将用作初始屏幕,并且导航器上的初始路由属性将被忽略。

在我们的例子中,这会导致TabBScreen1永远不会安装。因此,我们无法重置这条路线。如果我们initial: false在导航到嵌套屏幕时提供,导航框架将不会用作TabBScreen2初始路线,而是TabBScreen1. 如果我们这样做,我们可以通过再次按下按钮来重置路线TabBStack

navigation.navigate("TabBStack", { screen: "TabBScreen2", initial: false });
Run Code Online (Sandbox Code Playgroud)