繁体   English   中英

从 react-navigation pkg 抛出错误的 DrawerNavigator 中的 TouchableOpacity 调用 useNavigation 挂钩,问题正文的完整源代码

[英]Calling useNavigation hook from TouchableOpacity inside a DrawerNavigator from react-navigation pkg throwing error, full source on question body

我最近 4 天正在学习 react 和 react-native,因为需要构建一个移动应用程序并且在编写react-native应用程序时遇到以下问题:
经过一番研究,我找到了一种在 DrawerNavigator 的顶部栏中嵌入 TouchableOpacity 的方法,就在汉堡包按钮之后,它可以给我一个警报。
当我尝试用调用useNavigation().navigate('Login');来替换警报时,问题就来了。 从它的 onPress 属性内部,它会抛出下面的错误。
我想镜像 TouchableOpacity 上菜单项的行为进行导航。

 Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem., js engine: hermes
info Reloading app...

完整来源如下:

import * as React from 'react';
import { Button, Image, StyleSheet, Text, TouchableOpacity, View, Alert  } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import {
  createDrawerNavigator,
  DrawerContentScrollView,
  DrawerItemList,
} from '@react-navigation/drawer';
// https://reactnavigation.org/docs/use-navigation/
import { useNavigation } from '@react-navigation/native';

const getScreenCtx = content => {
  return (<View style={stl.boxCtx}>{content}</View>);
}

const Home = ({ navigation }) => {
  return ( getScreenCtx(<Text style={stl.boxDescr}>Home</Text>) );
}
const Login = ({ navigation }) => {
  return ( getScreenCtx(<Text style={stl.boxDescr}>Login</Text>) );
}
const Logout = ({ navigation }) => {
  return ( getScreenCtx(<Text style={stl.boxDescr}>Logout</Text>) );
}

const navToLogin = () => {
  useNavigation().navigate('Login');
}

const NestedTabBar = props => {
  return (
  <>
    <TouchableOpacity
      style={stl.itemNav}
      onPress={
        () => {
          //Alert.alert('NavigateToLogin');
          navToLogin();
        }
    } >
      <Text>[NavigateToLogin]</Text>
    </TouchableOpacity>
  </>
  );
}

const ContentTopWideHamburgBar = props => {
  return <NestedTabBar />;// <Text style={stl.hamburgBar}>ContentTopHamburgBar</Text>
}
const ContentColapsibleSideBarMenuHeader = props => {
  return <Text style={stl.sideMenuHeader}>SideBarMenuHeader</Text>
}
const ContentColapsibleSideBarMenuFooter = props => {
  return <Text style={stl.sideMenuFooter}>SideBarMenuFooter</Text>
}

const ContentColapsibleSideBarMenu = props => {
  return (
    <View style={stl.sideBarMenu}>
      <DrawerContentScrollView {...props}>
        <ContentColapsibleSideBarMenuHeader/>
        <DrawerItemList {...props} />
      </DrawerContentScrollView>
      <ContentColapsibleSideBarMenuFooter/>
    </View>
  );
}

const Drawer = createDrawerNavigator();

const ContentItensNavigationRouteMap = () => {
  return (
    <>
      <Drawer.Screen component={Home} name='Home' />
      <Drawer.Screen component={Login} name='Login' />
      <Drawer.Screen component={Logout} name='Logout' />
    </>
  );
}

const DrawerNavigator = () => {
  return (
    <Drawer.Navigator
        screenOptions={
          {
            headerStyle: { backgroundColor: 'magenta', },
            headerTintColor: 'white', // hamburg color
            headerTitleStyle: { fontWeight: 'bold', },
            headerTitle: (props) => <ContentTopWideHamburgBar {...props} />
          }
        }
        contentOptions={
          {
            activeTintColor: 'red',
            activeBackgroundColor: 'red',
            inactiveTintColor: 'red',
            inactiveBackgroundColor: 'red',
          }
        }
        drawerContent={props => <ContentColapsibleSideBarMenu {...props} />} >
          {ContentItensNavigationRouteMap()}
    </Drawer.Navigator>
  );
};

export default function ShellNavigator() {
  return (
    <NavigationContainer>
      <DrawerNavigator />
    </NavigationContainer>
  );
}

const stl = StyleSheet.create({
  boxDescr: {
    fontSize: 30,
    margin: 10,
    padding:10,
    backgroundColor: 'lightblue',
    color: 'red',
  },
  boxCtx:{
    display: 'flex',
    flex: 1,
    fontSize: 30,
    margin: 0,
    backgroundColor: 'yellow',
  },
  hamburgBar: {
    fontSize: 20,
    margin: 10,
    backgroundColor: 'pink',
  },
  sideMenuHeader: {
    fontSize: 20,
    margin: 10,
    backgroundColor: 'blueviolet',
  },
  sideMenuFooter: {
    fontSize: 20,
    margin: 10,
    backgroundColor: 'purple',
  },
  sideBarMenu: {
    flex: 1,
    fontSize: 20,
    margin: 10,
    backgroundColor: 'greenyellow',
  },
  itemNav: {
    fontSize: 40,
    padding: 10,
    backgroundColor: 'red',
  },
});

这里的navToLogin是一个独立的函数,而不是一个函数组件。 Hooks 需要在一个功能组件中才能使用。 下面的代码应该可以使用navToLogin将函数移动到功能组件内。

const NestedTabBar = props => {
  const navigation = useNavigation();

  const navToLogin = () => {
    navigation.navigate('Login');
  }
  
  return (
  <>
    <TouchableOpacity
      style={stl.itemNav}
      onPress={
        () => {
          //Alert.alert('NavigateToLogin');
          navToLogin();
        }
    } >
      <Text>[NavigateToLogin]</Text>
    </TouchableOpacity>
  </>
  );
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM