【问题标题】:React Native: Passing navigation route as props into dynamically rendered componentReact Native:将导航路线作为道具传递给动态呈现的组件
【发布时间】:2020-06-16 23:56:13
【问题描述】:

我正在构建一个应用程序,其中几个屏幕具有动态呈现的卡片,这些卡片映射到名为ENTRIES 的对象数组。可以按下这些卡片中的每一个来导航到相应的屏幕,但是,我似乎无法让导航工作。

我将 ENTRIES 中的 screen 值作为道具从 Settings.js 屏幕传递到 ClickableCard 组件,然后将其作为 this.props.navigation.navigate(screen) 传递到 TouchableOpacity onClick。

但是我不断收到以下错误TypeError: undefined is not an object (evaluating '_this3.props.navigation.navigate')

下面是代码示例:

App.js 文件

    import React from 'react;
    import {createMaterialBottomTabNavigator} from '@react-navigation/material-bottom-tabs';
    import {NavigationContainer} from '@react-navigation/native';
    import {createStackNavigator} from '@react-navigation/stack';
    import Home from './src/screens/Home';
    import SettingsScreen from './src/screens/SettingsScreen';
    import PrivacyScreen from './src/screens/PrivacyScreen';
    import NotificationsScreen from './src/screens/NotificationsScreen';
    import SoundsScreen from './src/screens/SoundsScreen';
    import ThemeScreen from './src/screens/ThemeScreen';

    const PrivacyStack = createStackNavigator();
    const SettingsStack = createStackNavigator();
    const AuthStack = createStackNavigator();
    const MainStack = createStackNavigator();
    const Tabs = createMaterialBottomTabNavigator();

    const TabNavigator = () => {
     return (
    <Tabs.Navigator
    initialRouteName="Home"
    <Tabs.Screen
    name="Home"
    component={HomeStack}
    />
    Tabs.Screen
    name="Settings"
    component={SettingsStack}
    children={this.SettingsStack}
    </Tabs.Navigator>
    )
    }

const AuthStack = () => (
  <AuthStack.Navigator>
    <AuthStack.Screen
      name="Auth"
      component={Auth}
    />
  </AuthStack.Navigator>
);


    const SettingsStackScreen = () => (
      <SettingsStack.Navigator>
        <SettingsStack.Screen
          name="Settings"
          component={Settings}
        />
        <SettingsStack.Screen
          name="Privacy"
          component={PrivacyStack}

        />
        <SettingsStack.Screen
          name="Theme"
          component={ThemeScreen}

        />
        <SettingsStack.Screen
          name="Notifications"
          component={NotificationsScreen}

        />
        <SettingsStack.Screen
          name="Sound"
          component={SoundsScreen}

        />
      </SettingsStack.Navigator>
    );

    const PrivacyStack = () => (
      <PrivacyStack.Navigator>
        <PrivacyStack.Screen
          name="Privacy"
          component={PrivacyScreen}
        />
        <PrivacyStack.Screen
          name="Notifications"
          component={NotificationsScreen}

        />
      </PrivacyStack.Navigator>
    );

const App = () => {
return (
    <NavigationContainer ref={navigationRef}>
      <MainStack.Navigator>
        <MainStack.Screen name="Tabs" component={TabNavigator} />
        <MainStack.Screen
          name="Auth"
          component={AuthStack}
          options={{gestureEnabled: false}}
        />
      </MainStack.Navigator>
    </NavigationContainer>
)
}

Settings.js 文件

    import React, {Component} from 'react';
    import {TouchableOpacity, ScrollView} from 'react-native;
import ClickableCard from './ClickableCard'

        export default class Settings extends Component {
        render(screen, index) {
        return (
                  <ScrollView>
                    {ENTRIES.map((entry, index) => (
    <ClickableCard screen={entry.screen} key={entry.index}/>

                    ))}
                  </ScrollView>
        )
        }

        export default Settings

ClickableCard.js 组件

                import React, {Component} from 'react';
                import {TouchableOpacity, ScrollView} from 'react-native;

                    export default class ClickableCard extends Component {
          constructor(props) {
            super(props);
        }
                    render() {

const {
screen,
key
} = this.props
                    return (
                            <TouchableOpacity

                                key={key}
                                onPress={() => this.props.navigation.navigate(screen)}>
                              </TouchableOpacity>
                    )
                    }
    }

entries.js 文件

import React from 'react';

export const ENTRIES = [
{
name: "Theme",
screen: "ThemeScreen",
},
{
name: "Sounds",
screen: "SoundsScreen",
},
{
name: "Notifications",
screen: "NotificationsScreen",
},
] 

【问题讨论】:

  • Settings.js 中,您永远不会在调用map 之前导入ENTRIES。这只是您的问题中的一个错字吗?
  • 哦,是的,这是一个错字。我的错!很好发现
  • ClickableCard 不会从父 Settings 组件继承 navigation 属性。您要么需要显式传递它,要么使用下面提到的useNavigation 钩子。

标签: javascript reactjs react-native


【解决方案1】:

您正在尝试访问导航堆栈之外的导航。

如果您使用的是功能组件,则可以使用 useNavigation 挂钩,但由于这是一个基于类的组件,您必须将导航作为道具发送,或者您可以按照documentation 中的建议执行以下操作

import { useNavigation } from '@react-navigation/native';
class ClickableCard extends Component {
  constructor(props) {
    super(props);
  }
  render() {
    const { screen, key } = this.props;
    return (
      <TouchableOpacity
        key={key}
        onPress={() =>
          this.props.navigation.navigate(screen)
        }></TouchableOpacity>
    );
  }
}

const ClickableCardWithNavigation= (props) {
  const navigation = useNavigation();

  return <ClickableCard {...props} navigation={navigation} />;
}

export default connect(ClickableCardWithNavigation)(TodoList)

【讨论】:

  • 这行得通 - 但是我需要使用 export default connect(mapStateToProps)(ClickableCard); 组件连接到我的 Redux 商店。由于我不能在组件内有两个导出,我该如何使用 connect mapStateToProps 以及您提供的解决方案?
  • 最简单的选择是使用功能组件,因为您没有使用该类的任何功能,并且如果您想将其与 redux 一起使用,请将导出函数分配给 const 并在您的 mapstate 中使用它道具
  • 用连接更新了答案,请检查:)
猜你喜欢
  • 1970-01-01
  • 2017-10-20
  • 1970-01-01
  • 2022-11-10
  • 2020-05-12
  • 2022-01-24
  • 2022-01-24
  • 1970-01-01
相关资源
最近更新 更多