簡體   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