You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native导航异常:Invalid hook call error问题求助

React Native导航错误修复方案

错误原因分析

  1. Hook规则违反:在函数组件外部调用了useNavigation钩子,不符合React Hooks只能在组件内部或自定义Hook中调用的规则。
  2. 导航上下文缺失:Header组件被放在NavigationContainer外部,无法获取导航上下文,导致导航功能失效。
  3. 错误依赖导入:导入了Web端路由库react-router-dom的useNavigate,React Native应用应使用@react-navigation系列库实现导航,无需该依赖。
  4. 组件注册失败:上述错误导致应用初始化异常,触发AppRegistry.registerComponent未执行的错误。

修复步骤及代码修改

1. 修正app.tsx

移除外部的useNavigation调用,删除无效依赖,调整组件结构确保Header在导航上下文内:

import React, { useEffect } from 'react';
import { StyleSheet, View } from 'react-native';
import Footer from './components/footer';
import Header from './components/header';
import Home from './screens/home/home';
import Login from './screens/login/login';
import ScheduleBody from './screens/schedule/body';
import { NavigationContainer } from '@react-navigation/native';
import { StackParams } from './components/navigation';
import colors from './components/colors';
import AsyncStorage from "@react-native-async-storage/async-storage";
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import PersonalRecords from './screens/pr/personalRecords';
import UserPage from './screens/user/userPage';
import Protein from './screens/protein/protein';

const Stack = createNativeStackNavigator<StackParams>();

const App = () => {
  const [loggedIn, setLoggedIn] = React.useState(false);
  const [initialRouteName, setInitialRouteName] = React.useState('Login');

  const checkLoggedIn = async () => {
    const user = await AsyncStorage.getItem('user');
    if (user) {
      setLoggedIn(true);
      setInitialRouteName('Home');
    }
  };

  useEffect(() => {
    checkLoggedIn();
  }, []);

  return (
    <NavigationContainer>
      <View style={styles.container}>
        {/* Header现在处于导航上下文内部,可正常获取导航实例 */}
        {!loggedIn && <Header />}
        <Stack.Navigator initialRouteName={initialRouteName}>
          <Stack.Screen name='Home' component={Home} options={{ headerShown: false }}/>
          <Stack.Screen name="Schedule" component={ScheduleBody} options={{ headerShown: false }} />
          <Stack.Screen name="PersonalRecords" component={PersonalRecords} options={{ headerShown: false }} />
          <Stack.Screen name="Login" component={Login} options={{ headerShown: false }} /> 
          <Stack.Screen name="User" component={UserPage} options={{ headerShown: false }} />
          <Stack.Screen name="Protein" component={Protein} options={{ headerShown: false }} />
        </Stack.Navigator>
        {!loggedIn && <Footer />}
      </View>
    </NavigationContainer>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: colors.background,
  },
});

export default App;

2. 修正header.tsx

直接在组件内部使用useNavigation钩子,无需通过props传递导航实例:

import React, { useEffect } from 'react';
import { View, Text, StyleSheet, Image, TouchableOpacity } from 'react-native';
import colors from './colors';
import { calendar, activeWorkout, restDay, streak_25 } from '../assets/assets';
import { StackParams } from './navigation';
import { useNavigation } from '@react-navigation/native';
import { StackNavigationProp } from '@react-navigation/stack';

type HeaderNavigationProp = StackNavigationProp<StackParams, 'Schedule'>;

const Header = () => {
  const navigation = useNavigation<HeaderNavigationProp>();
  const [hasWorkout, setHasWorkout] = React.useState(false);
  
  useEffect(() => {
    setHasWorkout(false);
  }, []);

  const toggleActiveWorkout = () => {
    setHasWorkout(!hasWorkout);
  };

  const handleCalender = () => {
    navigation.navigate('Schedule');
  };

  return (
      <View>
        <View style={styles.centerContainer} >
            {hasWorkout ? (
                <Image style={styles.textLeft} source={ activeWorkout } />
            ) : (
                <Image style={styles.textLeft} source={ restDay } />
                )}
            <Text style={styles.textCenter}>25<Image style={styles.streak} source={streak_25}/></Text>
            <TouchableOpacity style={styles.textRight} activeOpacity={0.5} onPress={handleCalender}>
                <Image source={calendar} />
            </TouchableOpacity>
        </View>
      </View>
    );
};

const styles = StyleSheet.create({
  centerContainer: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    paddingHorizontal: 20,
    paddingVertical: 10,
    backgroundColor: colors.primary,
  },
  textLeft: {
    width: 40,
    height: 40,
  },
  textCenter: {
    fontSize: 24,
    fontWeight: 'bold',
    color: colors.white,
  },
  streak: {
    width: 20,
    height: 20,
    marginLeft: 5,
  },
  textRight: {
    width: 40,
    height: 40,
  },
});

export default Header;

3. 清理无效依赖

删除app.tsx中import { useNavigate } from 'react-router-dom';这一行,并执行以下命令移除无用依赖:

npm uninstall react-router-dom

4. 重启Metro服务

停止当前运行的Metro服务,回到项目根目录执行命令重启:

npx react-native start --reset-cache

验证修复

完成上述修改后重新运行应用,导航功能应正常工作,所有错误信息不再出现。

内容的提问来源于stack exchange,提问作者david backx

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 19:24:55