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

React Native组件与Hooks报错:Invalid hook call排查与解决

问题解答

1. 报错原因

你在flightService.ts的fetchAssignedFlights普通异步函数里调用了useAuthStore Hook,这直接违反了React Hooks的核心规则:Hooks只能在函数组件的顶层或自定义Hook的顶层调用,绝不允许在普通函数、异步回调、循环或条件判断中调用Hook。

当useQuery执行时会调用fetchAssignedFlights,此时在这个普通函数里的Hook调用就触发了"Invalid hook call"错误。

2. 正确解决方案

步骤1:修改请求函数,移除内部Hook调用

把fetchAssignedFlights改成纯异步函数,所需的userId从外部传入:

// flightService.ts
export async function fetchAssignedFlights(userId: number): Promise<AssignedFlight[]> {
  const response = await api.get<AssignedFlight[]>(
    `/assign/flights-by-agent/${userId}`,
  );
  return response.data;
}

步骤2:在自定义Hook中处理依赖参数

在useFlightList这个自定义Hook里获取用户信息,再传递给请求函数,同时优化请求触发时机:

// useFlightList.ts
import { useQuery, UseQueryResult } from "@tanstack/react-query";
import { AssignedFlight, fetchAssignedFlights } from "../services/flightService";
import useAuthStore from "../stores/authStore";

export function useFlightList(): UseQueryResult<AssignedFlight[]> {
  const { getUser } = useAuthStore();
  const user = getUser();
  
  return useQuery<AssignedFlight[]>({
    queryKey: ["flights", user.id], // 将userId加入queryKey,用户切换时自动重新请求
    queryFn: () => fetchAssignedFlights(user.id),
    enabled: !!user?.id, // 仅当userId存在时才发起请求,避免无效调用
  });
}

步骤3:清理FlightList组件冗余代码

移除重复的isLoading和isError判断:

// FlightList.tsx
import { ActivityIndicator, Text, View } from "react-native";
import { useFlightList } from "../../hooks/useFlightList";

export default function FlightList() {
  const { data: flights, isLoading, isError, error } = useFlightList();

  if (isLoading) {
    return (
      <View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
        <ActivityIndicator size="large" color="#043150" />
        <Text style={{ marginTop: 10 }}>Loading flights...</Text>
      </View>
    );
  }

  if (isError) {
    console.error("Flight loading error:", error);
    return (
      <View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
        <Text style={{ color: "red" }}>Failed to load flights</Text>
        <Text style={{ fontSize: 12, marginTop: 5 }}>
          {error?.message || "Unknown error occurred"}
        </Text>
      </View>
    );
  }

  return (
    <View>
      <Text>List flights</Text>
      {flights && flights.length > 0 ? (
        <Text>Found {flights.length} flights</Text>
      ) : (
        <Text>No flights available</Text>
      )}
    </View>
  );
}

嵌套组件使用useQuery的核心要点

  • 所有Hook调用必须在函数组件或自定义Hook的顶层,不能嵌套在任何代码块中
  • 数据请求函数保持纯函数特性,所需依赖从外部传入,不要在内部调用Hook
  • 利用queryKey传递依赖参数,确保依赖变化时自动触发重新请求
  • 通过enabled选项控制请求时机,避免依赖未就绪时发起无效请求

内容的提问来源于stack exchange,提问作者Mohamed Amine Bejaoui

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 11:27:12