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

React Hooks中useQuery依赖参数变更时查询执行延迟问题

问题根因
  • useQuery的查询键(queryKey)写死为固定值['chargen']。React Query 依赖queryKey的变更判断是否需要重新执行查询,当入参lager、access_token变化时,固定的queryKey会让React Query认为当前查询没有变化,不会主动触发重取。
  • 传入useChargen的lager参数通过getValues("selWaren")获取,不具备响应式能力。getValues是react-hook-form提供的手动读值方法,不会订阅表单字段变化,也不会在字段更新时触发组件重渲染。只有当组件内其他state(比如sEingang/sLager)更新带动组件重渲染时,才会读到最新的selWaren值,这就是查询触发有明显延迟的核心原因。
修复方案
  1. 把所有影响查询结果的动态参数加入queryKey,让React Query能感知到依赖变化:
export default function useChargen({access_token, lager}) {
  return useQuery(
    // 将bartlhpo_id、access_token加入查询键
    ['chargen', lager?.bartlhpo_id, access_token?.access_token], 
    async () => {
      const url = new URL('http://127.0.0.1:3005/api/chargen');
      const params = {bartlhpo_id: lager?.bartlhpo_id }
      url.search = new URLSearchParams(params).toString();
      const response = await fetch(url, {
        method: 'GET',
        headers: new Headers({
          Authorization: `Bearer ${access_token.access_token}`,
        })
      })
      if (!response.ok) {
        throw new Error(response.status);
      }
      return response.json();
    }, 
    {
      enabled: !!lager?.bartlhpo_id && !!access_token?.access_token
    }
  )
}
  1. 替换getValues的取值方式,用响应式方法获取表单selWaren字段的值,保证字段变化时组件能自动重渲染,将最新值传给useChargen:
export default function Home() {
  const [sEingang, setSEingang] = useState([]);
  const [sLager, setSLager] = useState("");
  const [menge, setMenge] = useState(0);
  const context = React.useContext(AuthContext);
  const { data: warendata } = useWaren(context.access_token);
  const { data: lagerdata } = useGetLager(context.access_token);
  const methods = useForm({
    resolver: yupResolver(validationShema),
    mode: "all",
  });
  const { reset, control } = methods;
  // 用useWatch订阅selWaren字段变化,值更新时自动触发组件重渲染
  const selWaren = useWatch({ control, name: "selWaren" })

  // 传入响应式的selWaren值
  const { data: chargendata } = useChargen({
    access_token: context.access_token,
    lager: selWaren,
  });

  React.useEffect(() => {
    async function getToken() {
      await context.setTokenSilently();
    }
    const interval = setInterval(getToken, 30000);
    return () => clearInterval(interval);
  }, []);
  

  return (
    <>
      <CssBaseline />
      <ButtonAppBar name={"Wareneingänge"} back={false} onClick={reset} />
      <Grid
        container
        spacing={0}
        direction="column"
        alignItems="center"
        justifyContent="center"
        style={{ minHeight: "50vh" }}
      >
        <Grid item xs={3}>
          <FormProvider {...methods}>
            <form>
              <MySelect
                formname={"selWaren"}
                data={warendata}
                name={"Wareneingänge"}
                selected={sEingang}
                setSelected={setSEingang}
              />

              <MySelect
                formname={"selLager"}
                data={lagerdata}
                name={"Freie Lagerplätze"}
                selected={sLager}
                setSelected={setSLager}
              />

              <MySelect
                formname={"selChargen"}
                data={chargendata}
                name={"Freie Chargenplätze"}
                selected={sLager}
                setSelected={setSLager}
              />
              <FormDialog func={() => {}} menge={menge} setMenge={setMenge} />
            </form>
          </FormProvider>
        </Grid>
      </Grid>
    </>
  )
}

补充说明:getValues仅适合在事件回调(如表单提交、按钮点击)中一次性读取表单值,不能用来给Hook或组件传递响应式依赖,它不会触发视图更新。修复后不需要手动调用refetch,依赖变更时查询会自动触发。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 23:57:14