为什么我的 React Query 查询函数在应该禁用的时候却被调用了?

问题描述 投票:0回答:1

我想有条件地设置在 React 查询函数 (

useSpeciesCodes.js
) 中调用的参数和获取函数,以便基于 URL 查询从两个 API 端点之一进行获取(获取函数是
getSpeciesCodesByRegion
getSpeciesCodesByAddress
)和搜索参数。当参数和函数定义从另一个钩子(
useGetSpeciesCodesFunction.js
)返回时,查询函数才应该运行。

/**
 * 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 {
    status,
    data: speciesCodes,
    error,
  } = useQuery({
    queryKey: ["speciesCodes", params],
    queryFn: () => speciesCodesFunction(params),
    enabled: !!(params && speciesCodesFunction)
  });

  return { status, error, speciesCodes };
}
/**
 * useGetSpeciesCodesFunction.js
 */

import { useEffect, useState } from "react";
import { getSpeciesCodesByAddress, getSpeciesCodesByRegion } from "../services/apiEBird";
import { getAddressbyCoordinates } from "../services/apiRadar";
import { useParams, useSearchParams } from "react-router-dom";

export function useGetSpeciesCodesFunction() {
    const { layer } = useParams();
    const [searchParams] = useSearchParams();
    const lat = searchParams.get("lat");
    const lng = searchParams.get("lng");
    const [params, setParams] = useState(null);
    const [speciesCodesFunction, setSpeciesCodesFunction] = useState(null)

    useEffect(
        () => {
            async function handleLocation(layer, lat, lng) {
                // If layer is state or country, convert option value to ISO standardized code to get region code for eBird API
                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 {
                    const radius = 25;
                    setParams({ lat, lng, radius });
                    setSpeciesCodesFunction(getSpeciesCodesByAddress);
                }
            }
            handleLocation(layer, lat, lng);
        }
        , [layer, lat, lng]
    )
    console.log(params, speciesCodesFunction)
    return { params, speciesCodesFunction }

}

输出显示,在

getSpeciesCodesByRegion
钩子返回非空值之前,正在调用获取函数
useGetSpeciesCodesFunction.js
,而由于 'enabled' 选项中的条件,不应调用该函数。我感到困惑的另一个问题/原因是为什么从
useGetSpeciesCodesFunction.js
返回的函数是 Promise 而不是函数定义,但它被 React Query 作为函数定义处理。

1. useGetSpeciesCodesFunction.js:44 null null
2. apiRadar.js:8 getAddressbyCoordinates
3. apiEBird.js:11 getSpeciesCodesByRegion null
4. useGetSpeciesCodesFunction.js:44 US-WA Promise {<pending>}
5. useGetSpeciesCodesFunction.js:44 US-WA Promise {<fulfilled>: Array(0)}

这个问题让我发疯。我尝试将

useGetSpeciesCodesFunction
异步函数包装在多个异步等待层中,考虑到它是一个异步问题,并将异步函数移到钩子之外或移动到其他钩子中。我尝试了一种解决方法来解决一个错误,其中报告启用的选项不起作用(https://github.com/TanStack/query/issues/1196),但无论如何都会调用查询函数。当然,我也尝试过简单地将启用选项设置为 false,它仍然可以运行。我希望
useGetSpeciesCodesFunction
根据 URL 和搜索参数返回参数和函数定义。我想要
useSpeciesCodes
调用该函数并传递参数,并从获取 API 返回数据。

这个问题被否决了。如您所见,这是我在 Stack Overflow 上发布的第一个问题。如果它不符合标准或可以改进,我将非常感谢反馈。当它被简单地否决时,我不知道如何改进它。

javascript reactjs react-hooks async-await react-query
1个回答
0
投票

我发现进行 API 调用并使得 React Query 查询函数在禁用时被调用的原因是因为 useState 挂钩无法存储函数定义。通过尝试将函数存储在状态中,它会触发对 API 函数的调用。修复方法只是将回调函数传递给设置器:

setSpeciesCodesFunction(() => getSpeciesCodesByRegion)

如何使用 useState 存储函数

© www.soinside.com 2019 - 2024. All rights reserved.