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

React中Invalid hook call错误:配置文件误用useState Hook的排查

解决React Hook调用错误:Invalid hook call

错误原因

你触发的Error: Invalid hook call. Hooks can only be called inside of the body of a function component错误,核心是违反了React Hooks的使用规则:Hooks只能在函数组件的顶层或者自定义Hook内部调用,不能在普通模块的全局作用域直接使用。你在配置文件的顶层作用域声明useState,完全不符合规范。

同时原代码存在另一个问题:导出的userCurrentWindow、userDrivingStatus等依赖状态的变量是一次性赋值的,即使后续调用setState更新状态,这些导出变量也不会同步更新,无法实现状态共享的需求。

解决方案:用自定义Hook封装状态与操作

将状态逻辑封装成自定义Hook,既符合Hooks规则,又能让组件获取实时更新的状态值。

1. 修改配置文件(重命名为useUserAuth.js)

import React, { useState, useMemo } from 'react'

export const useUserAuth = () => {
  // 在自定义Hook内部声明状态,符合规则
  const [state, setState] = useState({
    drivingStatus: false, 
    currentWindow: 'driver'
  });

  // 用函数式更新确保获取最新状态
  const drivingRequest = () => {
    setState(prevState => ({
      ...prevState, 
      drivingStatus: !prevState.drivingStatus
    }));
  }

  const switchWindow = () => {
    setState(prevState => ({
      ...prevState, 
      currentWindow: prevState.currentWindow === 'driver' ? 'user' : 'driver'
    }));
  }

  // 静态用户信息(无需更新的常量)
  const staticUserInfo = {
    userFirstName: 'xxxx',
    userLastName: 'xxxx',
    userCountry: '',
    userCountryStatus: 'active',
    userRegion: '', 
    userIso: '', 
    userIso3: '', 
    userLocale: 'en-US', 
    userLanguage: '',
    userWalletBalance: 0,
    userNotification: 0,
    userAccountType: 'driver',
    userDriverID: ''
  };

  // 依赖状态的计算值,用useMemo缓存避免重复计算
  const computedValues = useMemo(() => ({
    userCurrentWindow: state.currentWindow,
    userDrivingStatus: state.drivingStatus,
    userAverageRating: staticUserInfo.userAccountType === 'driver' && state.currentWindow === 'driver' ? 3.9 : 2.8
  }), [state, staticUserInfo.userAccountType]);

  // 合并所有需要导出的内容
  return {
    ...staticUserInfo,
    ...computedValues,
    drivingRequest,
    switchWindow
  };
}

2. 修改引用组件(CustomDrawer.js)

import React from "react";
import { View, Text, Pressable, TouchableOpacity } from "react-native";
import { DrawerContentScrollView, DrawerItemList } from '@react-navigation/drawer';
import { useNavigation } from '@react-navigation/native';
import { useUserAuth } from './useUserAuth'; // 导入自定义Hook
import Icon from 'react-native-vector-icons/MaterialIcons';
import AntDesign from 'react-native-vector-icons/AntDesign';

const CustomDrawer = (props) => {
  const navigation = useNavigation();
  // 在组件内部调用自定义Hook,获取实时状态和方法
  const { 
    userFirstName, 
    userLastName, 
    userAverageRating, 
    userWalletBalance, 
    userIso3, 
    userNotification, 
    userCurrentWindow, 
    userAccountType, 
    userDriverID, 
    userDrivingStatus, 
    drivingRequest, 
    switchWindow 
  } = useUserAuth();

  return (
    <View>
        <Text>User first name: {userFirstName}</Text>
        {/* 示例:添加触发状态更新的按钮 */}
        <Pressable onPress={drivingRequest} style={{marginTop: 10}}>
          <Text>{userDrivingStatus ? '停止接单' : '开始接单'}</Text>
        </Pressable>
        <Pressable onPress={switchWindow} style={{marginTop: 10}}>
          <Text>切换窗口:{userCurrentWindow}</Text>
        </Pressable>
        {/* 其他组件内容 */}
    </View>
  )
}

export default CustomDrawer;

关键说明

  • 自定义Hook遵循Hooks规则,只能在函数组件或其他自定义Hook内部调用,彻底解决原错误。
  • 使用函数式更新(setState(prevState => ...))避免闭包陷阱,确保每次更新都基于最新的状态值。
  • 用useMemo缓存计算值,避免组件重渲染时重复执行计算逻辑,优化性能。
  • 所有状态和方法通过自定义Hook统一管理,组件调用后能实时获取最新状态,解决了原代码中状态更新后导出变量不同步的问题。

内容的提问来源于stack exchange,提问作者Festus Akushie

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 23:19:00