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值,这就是查询触发有明显延迟的核心原因。
修复方案
- 把所有影响查询结果的动态参数加入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 } ) }
- 替换
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
相关产品推荐
相关产品推荐

