【问题标题】:navigating from a tab screen to a stack screen从选项卡屏幕导航到堆栈屏幕
【发布时间】:2022-01-20 19:14:56
【问题描述】:

对于 IOS 应用程序,我有一个在我的选项卡导航器中调用的堆栈。我正在尝试从底部选项卡屏幕导航到堆栈中的屏幕,但出现以下错误。

undefined 不是一个对象(评估 '_this.props.navigation.navigate')

我想在所有屏幕上呈现底部标签。我注意到这会导致 goBack() 以及其他地方出现一些有趣的问题。

如何从底部标签屏幕导航到堆栈屏幕?

当前的实施是一种不好的做法吗?

我已经提供了这个demo 以及下面的代码。我认为这与道具传递有关。

const Tab = createBottomTabNavigator();

function MyTabs() {
  return (

     <Stack.Navigator
     initialRouteName="Home">        
      <Stack.Screen name="Home" component= {Home} options={{headerShown: false}}/>
      <Stack.Screen name="Screen1" component= {Screen1} options={{headerShown: false}}/> 
    </Stack.Navigator>
);

);
}

export default function App() {

  return (
  <NavigationContainer>
    <Tab.Navigator
    initialRouteName="Home"
    screenOptions={{
      tabBarActiveTintColor: '#F60081',
      tabBarInactiveTintColor: '#4d4d4d',
      tabBarStyle: {
        backgroundColor: '#d1cfcf',
        borderTopColor: 'transparent',
      },
    }} 
  >
    <Tab.Screen
      name="Home"
      component={MyTabs}
      options={{
        tabBarLabel: 'Home',
        headerShown: false,
        tabBarIcon: ({ color, size }) => (
          <MaterialCommunityIcons name="home" color={color} size={size} />
        ),
      }}
    />
    
  </Tab.Navigator>
</NavigationContainer>
);
}

const Stack = createStackNavigator();

import * as React from 'react';
import {
  Text,
  View,
  StyleSheet,
  TouchableOpacity,
  ImageBackground,
} from 'react-native';
const Images = [
  { id: '1', uri: require('./assets/snack-icon.png'), text: 'Test' },
  { id: '2', uri: require('./assets/snack-icon.png') /*text: "Test"*/ },
  { id: '3', uri: require('./assets/snack-icon.png') /*text: "Test"*/ },
  { id: '4', uri: require('./assets/snack-icon.png') /*text: "Test"*/ },
];

export default class Home extends React.Component {

thisNavigate = () => {
  this.props.navigation();
};

  renderList = (props) => {
    return Images.map((item, i) => {
      return (
          <TouchableOpacity
            onPress={() => this.props.thisNavigate.navigate('Screen2')}>
            <ImageBackground
              source={item.uri}
              style={{
                width: '100%',
                height: 100,
                shadowColor: '#000',
                shadowOffset: { width: 1, height: 4 },
                shadowOpacity: 1,
              }}
              imageStyle={{ borderRadius: 10 }}></ImageBackground>
          </TouchableOpacity>
      );
    });
  };

  render() {
    return <View style={{ flex: 1 }}>{this.renderList()}</View>;
  }
}


【问题讨论】:

  • 问题不在该屏幕上,问题将在您的选项卡屏幕上。您单击该功能的位置。如果您在主组件下使用单词“{navigation}”,请将其删除并使用“const navigation = useNavigation();”。它会解决你的问题。您还可以分享您的标签屏幕代码。
  • @TalhaAkbar 我更新了帖子以包含您提到的代码。当我添加 const 导航时,它给我的 useNavigation 是未定义的。在查看更新的代码后,我知道如何去做吗?感谢您的任何见解

标签: reactjs react-native


【解决方案1】:

在您的示例中,您的 Home 组件是:

export default class Home extends React.Component {
  render() {
    return <Screen1/> // here navigation is not passed because it is rendered not by navigator but manually
  }
}

只需删除它,从MyTabs 中删除它的Stack.Screen 并将initialRouteName 设置为Screen1,它就可以工作了。

编辑:

如果您想保持主页不变,请像这样传递导航:

export default class Home extends React.Component {
  render() {
    return <Screen1 navigation={this.props.navigation}/>
  }
}

或者使用useNavigation钩子代替Screen1中的道具来获得导航。

EDIT2:

工作demo

【讨论】:

  • 在我的整个项目中,我在主屏幕上使用条件渲染,我需要在那里返回那个屏幕。
  • 这似乎是正确的。我想我错过了一小部分。你介意看看我更新的代码和零食,看看我可能做错了什么吗?我认为问题在于我如何在 Screen1 中调用它。谢谢@Alexander Danilov
  • @JustinPriede 添加了工作演示。
【解决方案2】:

我认为你需要用Navigation HOC 包装你的组件 https://reactnavigation.org/docs/4.x/with-navigation/

那是因为你的组件不是直接来自组件Navigator,所以他们没有this.props.navigation,为了让你的组件在Class Component中有导航道具,你需要使用withNavigation HOC包装你的组件

示例:


// Screen1.js
class Home extends React.Component {
  renderList = (props) => {
    return Images.map((item, i) => {
      return (
          <TouchableOpacity
            onPress={() => this.props.navigation.navigate('Screen2')}>
            <ImageBackground
              source={item.uri}
              style={{
                width: '100%',
                height: 100,
                shadowColor: '#000',
                shadowOffset: { width: 1, height: 4 },
                shadowOpacity: 1,
              }}
              imageStyle={{ borderRadius: 10 }}></ImageBackground>
          </TouchableOpacity>
      );
    });
  };

  render() {
    return <View style={{ flex: 1 }}>{this.renderList()}</View>;
  }
}

export default withNavigation(Home);

抱歉,我认为 withNavigation 已从 v5 / v6 中删除

但你可以做一个这样的

import { useNavigation } from '@react-navigation/native';

// withNavigation.js
export default function withNavigation(WrappedComponent) {
   return (props) => {
      const navigation = useNavigation();
      return <Component navigation={navigation} {...props} />
   }
}

【讨论】:

  • 所以我花了一些时间尝试这个,但不幸的是我无法让它工作。不过我可能会犯错误。您是否确认这确实适用于我提供的演示?谢谢你花时间在这件事上,我比你知道的更感激。
猜你喜欢
  • 2020-07-27
  • 2022-10-07
  • 2021-12-03
  • 1970-01-01
  • 1970-01-01
  • 2021-03-30
  • 1970-01-01
  • 2021-02-10
  • 1970-01-01
相关资源
最近更新 更多