我想有条件地设置在 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 上发布的第一个问题。如果它不符合标准或可以改进,我将非常感谢反馈。当它被简单地否决时,我不知道如何改进它。
我发现进行 API 调用并使得 React Query 查询函数在禁用时被调用的原因是因为 useState 挂钩无法存储函数定义。通过尝试将函数存储在状态中,它会触发对 API 函数的调用。修复方法只是将回调函数传递给设置器:
setSpeciesCodesFunction(() => getSpeciesCodesByRegion)
。