【问题标题】:How can a TabNavigator child screen refer to parent StackNavigator?TabNavigator 子屏幕如何引用父 StackNavigator?
【发布时间】:2019-12-02 10:15:19
【问题描述】:

我正在尝试从子选项卡导航器导航到父堆栈导航器的屏幕。但是 this.props.navigation.navigate 只能导航到孩子的导航道具 '

//stack.js

const AppNavigator = createStackNavigator(
{
    DetailPage: DetailPage, //Screen A
    MainScreen: { .        //Screen B
        screen: MainScreen,
        navigationOptions: {
            header: null
        }
    }
    {
        initialRouteName: "MainScreen"
    }
}


//MainScreen.js

<View style={{ flex: 1 }}>
    <TabScreen />
</View>

//TabScreen.js

const TabScreen = createMaterialTopTabNavigator({
    Home: { 
        screen: HomeStack 
    },
    // Videos: { screen: Videos },
    Videos: {
        screen: Videos 
    },
    Shows: {
        screen: AllShows
    },
    Live: { 
        screen: Live
    }
})'

我想从 (TabNavigator)TabScreen 的主页导航到 (StackNavigator)AppNavigator 的 DetailPage。但是 OnPress 什么都不做。但是,它可以导航到 TabNavigator(子导航器)的不同屏幕。 请帮助我如何从子 TabNavigator 导航到父 StackNavigator

【问题讨论】:

标签: react-native react-native-android react-props stack-navigator react-native-tabnavigator


【解决方案1】:

不。你不能做这样的事情。您需要确保只定义了一个导航器。如果不是,则需要确保导航状态已连接,以便导航器相互了解。我强烈建议您使用单个根导航

参考Common Mistakes in react navigation

显式渲染多个导航器 大多数应用程序应该只在 React 组件内渲染一个导航器,这通常位于应用程序根组件附近的某个地方。一开始这有点违反直觉,但它对 React Navigation 的架构很重要。

您需要在一个地方(根目录)定义所有内容。如下所示

import React, { Component } from "react";
import { View, Text } from "react-native";
import { createStackNavigator, createAppContainer } from "react-navigation";
import { createMaterialBottomTabNavigator } from "react-navigation-material-bottom-tabs";

import Camera from "./screens/camera";
import Welcome from "./screens/welcome";

import Scanner from "./screens/scanner";
import Cards from ".//screens/cards";

const BottomNavigation = createMaterialBottomTabNavigator(
  {
    Scan: { screen: Scanner },
    Cards: { screen: Cards },
    Settings: { screen: Cards }
  },
  {
    initialRouteName: "Scan",
    shifting: true
  }
);
const AppNavigator = createStackNavigator({
  Welcome: {
    screen: Welcome,
    navigationOptions: { header: null }
  },
  Camera: {
    screen: Camera,
    navigationOptions: { header: null }
  },
  Home: {
    screen: BottomNavigation,
    navigationOptions: { header: null }
  }
});

export default createAppContainer(AppNavigator);

现在我相信您可以导航到不同的屏幕,因为所有内容都在一个导航器上定义。

【讨论】:

  • Adarsh 上述评论中提到的“withNavigation”怎么样
  • 您可以使用 withNavigation 获取导航道具,但由于根导航器不知道 MaterialTopNavigator,因此它不起作用
  • 我的问题有点不同,我想将选项卡上方的视图容器显示为页眉,将视图容器显示为页脚。我怎样才能只使用一个导航器?因此,我制作了一个名为主屏幕的新屏幕,其结构如下(顶部)标题(中间)TabNavigator(底部)页脚
  • 对于标题你可以使用导航选项标题为 TabNavigator .. 对于页脚你需要做一些事情,比如在导航器之外渲染页脚
  • 谢谢,这可以工作。只需要一点帮助,你能给我一些在导航器之外渲染页脚的例子吗?我是这里的新手
【解决方案2】:

你能试试这个吗?

//stack.js

const AppNavigator = createStackNavigator(
{
    DetailPage: DetailPage, //Screen A
    MainScreen: { .        //Screen B
        screen: MainScreen,
        navigationOptions: {
            header: null
        }
    },
    TabScreen : {
       screen : TabScreen
    },
    {
        initialRouteName: "TabScreen"
    }
}




//TabScreen.js

const TabScreen = createMaterialTopTabNavigator({
    Home: { 
        screen: HomeStack 
    },
    // Videos: { screen: Videos },
    Videos: {
        screen: Videos 
    },
    Shows: {
        screen: AllShows
    },
    Live: { 
        screen: Live
    }
},
    {
        initialRouteName: "Home"
    }
)'

【讨论】:

    【解决方案3】:
    this.props.navigation.dangerouslyGetParent().navigate('routeName', {});
    

    此外,如果您准备重构一些代码,您可以创建一个新屏幕并创建一些额外的组件,您可以为每个 TabNavigation 屏幕创建一个 MainTabScreen,然后:-


    App.js

    <NavigationContainer>
      <Stack.Navigator
        screenOptions={{
          headerShown: false
        }}
      >
        <Stack.Screen 
          name="login" 
          component={LogIn} 
          options={{title : 'LOG IN', headerShown: true}}
        />
        <Stack.Screen 
          name="client-tabs-main" 
          component={ClientTabsMain} 
        />
        ... Other Screens ...
      </Stack.Navigator>
    </NavigationContainer>

    ClientsTabMain.jsx

    <Tabs.Navigator 
        activeColor='white'
        barStyle={{backgroundColor: colors.primary}}
    
        >
        <Tabs.Screen
        name="home-tabs"
        component={HomeTab}
        options={{
          tabBarLabel: 'Home',
          tabBarIcon: ({ color }) => (
            <MaterialCommunityIcons name="home-outline" color={color}  size={18} />
          ),
        }}
      />
      <Tabs.Screen
        name="portfolio-tabs"
        component={PortfolioTab}
        options={{
          tabBarLabel: 'Portfolio',
          tabBarIcon: ({ color }) => (
            <MaterialCommunityIcons name="clock" color={color}  size={18} />
          )
        }}
    
      />
      ... Other Screens ...
    </Tabs.Navigator>

    PortfolioTabs.jsx

    <PortfolioStack.Navigator
      screenOptions={{
        headerShown: true
      }}
    >
    <PortfolioStack.Screen 
      name="portfolio" 
      component={Portfolio} 
      options={{
        title: 'Portfolio'
      }}
      />
      <PortfolioStack.Screen 
        name="transaction" 
        component={Transaction} 
      />
    </PortfolioStack.Navigator>

    并使用导航:-

    this.props.navigation.replace('client-tabs-main',{
          screen: 'portfolio-tabs',
          params: {
            screen: 'portfolio'
          }
        });
    

    【讨论】:

    • 正如@ThaJay 所说,虽然提供纯代码答案是可以接受的,但如果您还可以提供代码解释并帮助人们理解为什么 i> 它解决了这个问题。这可以减少后续问题的数量,并帮助新开发人员理解底层概念。 尤其是在用现有答案回答老问题时更是如此;在这种情况下,突出显示您的方法与现有答案的区别是很有用的。您介意用更多细节更新您的问题吗?
    【解决方案4】:
    createBottomTabNavigator({
        HomeTab: {
            screen: HomeStack,
                navigationOptions: {
                title: "Home",
                tabBarOnPress: this.handleTabPress
            }
        },
    MessagingTab: {
            screen: MessagingStack,
            navigationOptions: {
                title: "Messaging",
                tabBarOnPress: this.handleTabPress
            }
        }
    });
    
    handleTabPress = ({ navigation }) => {
        navigation.popToTop();
        navigation.navigate(navigation.state.routeName);
    }`
    

    【讨论】:

      猜你喜欢
      • 2017-12-18
      • 2019-01-28
      • 1970-01-01
      • 1970-01-01
      • 2018-11-17
      • 2018-04-26
      • 1970-01-01
      • 2021-08-12
      • 1970-01-01
      相关资源
      最近更新 更多