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

React Native导航调用useTranslation报Invalid hook call错误

问题原因

Invalid hook call报错是因为违反了React Hook的基本调用规则:Hook只能在React函数组件、自定义Hook的顶层作用域内调用。你代码里把const { t, i18n } = useTranslation();写在了组件外的模块顶层全局位置,完全不符合调用要求,所以直接抛错。
另外你原来写的BottomTabBar组件还缺少tab选中态绑定、点击跳转的逻辑,就算解决了hook报错,点击tab也不会正常切换页面。

修复步骤

  1. 删除模块顶层(所有组件外部)错误的useTranslation()调用代码
  2. 在需要用到翻译函数的BottomTabBar组件内部顶层调用useTranslation,拿到t翻译方法
  3. 把BottomNavigationTab上硬编码的title替换为t(你的翻译键)形式,同时补上tab选中和跳转逻辑

修正后的核心代码

修改StackNavigators.js如下:

import React, { useState, useEffect } from 'react';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { Keyboard } from 'react-native';
import TodayRates from '../pages/todayrates';
import Dashboard from '../pages/dashboard';
import UserService from '../services/userService';
import Profile from '../pages/profile';
import TodayActivities from '../pages/todayActivities';
import Tasks from '../pages/tasks';
import Task from '../pages/task';
import Settings from '../pages/settings';
import { BottomNavigation, BottomNavigationTab } from '@ui-kitten/components';
import { CreateTaskIcon } from '../assets/icons';

// For translation
import '../../i18n/i18n';
import { useTranslation } from 'react-i18next';
// 移除此处原来错误的顶层useTranslation调用

const { Navigator, Screen } = createBottomTabNavigator();

// 把BottomTabBar从单表达式箭头函数改成带内部逻辑的函数组件
const BottomTabBar = ({ navigation, state }) => {
  // 符合Hook规则:在组件顶层调用useTranslation
  const { t } = useTranslation();

  return (
    <BottomNavigation
      selectedIndex={state.index}
      onSelect={index => navigation.navigate(state.routeNames[index])}
    >
      {/* 替换为你语言包中对应的实际key即可 */}
      <BottomNavigationTab title={t('dashboard')}/>
      <BottomNavigationTab title={t('activities')} />
      <BottomNavigationTab
        icon={<CreateTaskIcon fill="#fff" width={30} height={30} />}
      />
      <BottomNavigationTab title={t('tasks')} />
      <BottomNavigationTab title={t('rates')} />
    </BottomNavigation>
  )
};

const StackNavigators = () => {
    const [user, setUser] = useState({});
    const [isKeyboardVisible, setIsKeyboardVisible] = useState(false);
    const getUser = async () => {
        await UserService.getCurrentUser().then((user) => {
            setUser(user);
        })
    }

    useEffect(() => {
        getUser();

        const showSubscription = Keyboard.addListener("keyboardDidShow", () => {
            setIsKeyboardVisible(true);
        });
        const hideSubscription = Keyboard.addListener("keyboardDidHide", () => {
            setIsKeyboardVisible(false);
        });
    
        return () => {
            showSubscription.remove();
            hideSubscription.remove();
        };
    }, [isKeyboardVisible]);

    const getVisibilityStyle = (keyboardVisibility, props) => {
        if (!keyboardVisibility){
            return <BottomTabBar {...props}/>;
        }
        return null;
    }

    return (
        <Navigator
            initialRouteName="Dashboard"
            tabBar={
                props => getVisibilityStyle(isKeyboardVisible, props)
            }>
            <Screen name="Dashboard" component={Dashboard} options={{ headerShown: false }} />
            <Screen name="Activities" initialParams={{ user: user }} component={TodayActivities} options={{ headerShown: false }} />
            <Screen name="+" component={Task} options={{ unmountOnBlur: true, headerShown: false }} />
            <Screen name="Tasks" component={Tasks} options={{ unmountOnBlur: true, headerShown: false }} />
            <Screen name="TodayRates" initialParams={{ user: user }} component={TodayRates} options={{ unmountOnBlur: true, headerShown: false }} />
            <Screen name="Profile" component={Profile} options={{ headerShown: false }} />
            <Screen name="Settings" component={Settings} options={{ headerShown: false }} />
            <Screen name="EditTask" component={Task} options={{ unmountOnBlur: true, headerShown: false }} />
        </Navigator>
    );
}

export default StackNavigators;

注意事项

  • 所有React Hook(包括useTranslation、useState、useEffect等)都不能在组件外的全局作用域、循环、条件分支、嵌套普通函数内调用,必须放在函数组件/自定义Hook的最顶层。
  • 代码里t函数传入的键名,需要和你en.json/es.json/no.json语言包里定义的键名完全对应,比如英文包里写"dashboard": "Dashboard"即可。
  • 你其他页面翻译正常,说明i18n初始化配置没有问题,不需要修改i18n.js的代码。

内容的提问来源于stack exchange,提问作者arild tarland

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 19:51:17