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

React Query查询函数禁用时仍执行及返回Promise异常问题排查

React Query 条件查询及函数引用错误修复方案

核心问题

  1. React Query的enabled条件生效前,getSpeciesCodesByRegion已被提前调用
  2. useGetSpeciesCodesFunction返回的speciesCodesFunction意外变成Promise(而非函数定义),导致React Query执行出错

修复步骤

1. 消除参数冗余,统一参数来源

原useGetSpeciesCodesFunction内部重复通过useParams/useSearchParams获取参数,与外部传入的参数产生不一致,是逻辑混乱的根源。修改后仅依赖外部传入的参数:

/**
 * useGetSpeciesCodesFunction.js
 */
import { useEffect, useState } from "react";
import { getSpeciesCodesByAddress, getSpeciesCodesByRegion } from "../services/apiEBird";
import { getAddressbyCoordinates } from "../services/apiRadar";

export function useGetSpeciesCodesFunction(layer, lat, lng) {
    const [params, setParams] = useState(null);
    const [speciesCodesFunction, setSpeciesCodesFunction] = useState(null);

    useEffect(() => {
        // 先校验参数有效性,避免无效异步请求
        if (!layer || lat === null || lng === null) {
            setParams(null);
            setSpeciesCodesFunction(null);
            return;
        }

        async function handleLocation() {
            try {
                if (layer === 'state') {
                    const { stateCode, countryCode } = await getAddressbyCoordinates(layer, lat, lng);
                    setParams(`${countryCode}-${stateCode}`);
                    // 直接赋值函数引用,不要加括号执行
                    setSpeciesCodesFunction(getSpeciesCodesByRegion);
                } else if (layer === 'country') {
                    const { countryCode } = await getAddressbyCoordinates(layer, lat, lng);
                    setParams(countryCode);
                    setSpeciesCodesFunction(getSpeciesCodesByRegion);
                } else {
                    setParams({ lat, lng, radius: 25 });
                    setSpeciesCodesFunction(getSpeciesCodesByAddress);
                }
            } catch (err) {
                console.error('参数解析失败:', err);
                setParams(null);
                setSpeciesCodesFunction(null);
            }
        }

        handleLocation();
    }, [layer, lat, lng]);

    return { params, speciesCodesFunction };
}

2. 强化查询启用条件,优化Query Key

确保只有当speciesCodesFunction是函数类型、且params有效时,才触发React Query查询,同时优化Query Key避免无效缓存:

/**
 * useSpeciesCodes.js
 */
import { useQuery } from "@tanstack/react-query";
import { useParams, useSearchParams } from "react-router-dom";
import { useGetSpeciesCodesFunction } from "./useGetSpeciesCodesFunction";

export function useSpeciesCodes() {
    const { layer } = useParams();
    const [searchParams] = useSearchParams();
    const lat = searchParams.get("lat");
    const lng = searchParams.get("lng");

    const { params, speciesCodesFunction } = useGetSpeciesCodesFunction(layer, lat, lng);

    // 严格校验:必须是函数+有效参数才启用查询
    const isQueryEnabled = typeof speciesCodesFunction === 'function' && params !== null;

    const {
        status,
        data: speciesCodes,
        error,
    } = useQuery({
        queryKey: isQueryEnabled ? ["speciesCodes", layer, params] : ["speciesCodes", "disabled"],
        queryFn: () => speciesCodesFunction(params),
        enabled: isQueryEnabled,
        // 可选:添加缓存策略减少重复请求
        staleTime: 5 * 60 * 1000, // 5分钟缓存有效期
    });

    return { status, error, speciesCodes };
}

3. 验证API函数导出正确性

确保apiEBird.js中导出的是函数定义,而非函数执行结果:

// apiEBird.js 正确示例
export async function getSpeciesCodesByRegion(regionCode) {
    const response = await fetch(`/api/ebird/region/${regionCode}`);
    return response.json();
}

export async function getSpeciesCodesByAddress(coords) {
    const { lat, lng, radius } = coords;
    const response = await fetch(`/api/ebird/address?lat=${lat}&lng=${lng}&radius=${radius}`);
    return response.json();
}

问题根源

  1. 提前调用API:原代码参数来源不统一,导致enabled条件出现短暂的误判,触发不必要的查询
  2. 函数变Promise:参数不一致引发逻辑分支错误,或误将函数执行结果(Promise)赋值给了speciesCodesFunction,修复参数传递后即可避免

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 14:32:45