react-Query如何切换动态URL触发数据重拉取解决响应异常
问题根因
页面渲染异常、多次点击才更新的问题和接口响应速度无关,是react-query用法不符合设计逻辑导致,核心问题有两个:
useQuery的查询键(queryKey)写死为固定字符串"definition":react-query基于queryKey做缓存匹配、依赖变更重拉逻辑,你没有把动态变化的word参数放入queryKey,react-query感知不到查询目标变了,不会主动发起新单词的请求,只会复用之前缓存的run对应结果。- 请求函数直接读取组件闭包内的
word状态,没有和查询参数做绑定,容易拿到闭包保存的陈旧值,发请求时用的还是上一轮渲染的旧单词。
补充:你在handleWordchange里调用setword后立刻打印word得到旧值,是React状态异步更新的正常特性,不属于bug。
修复步骤
- 将动态参数
word加入queryKey,queryKey使用数组格式,把word作为第二项。只要word值变化,react-query会自动识别查询依赖变更,立刻发起新请求。 - 请求函数不要直接读取闭包中的
word,通过react-query传入查询函数的context对象,从queryKey中取目标单词参数,彻底规避闭包陈旧值问题。 - 增加基础错误判断,避免接口返回异常格式时,读取
data[0]触发JS报错。
修复后的完整代码:
import React from "react"; import { useQuery } from "react-query"; import { useState } from "react"; import { Button } from "@chakra-ui/react"; const Word = () => { const [word, setword] = useState("run"); const handleWordchange = () => { setword(word === "run" ? "stop" : "run"); }; const fetchWord = async ({ queryKey }) => { const [, targetWord] = queryKey; const res = await fetch( `https://api.dictionaryapi.dev/api/v2/entries/en/${targetWord}` ); return res.json(); }; const { data, isLoading, isFetching, error } = useQuery( ["definition", word], fetchWord ); const getDefinition = () => { if (isLoading || isFetching) { return <h2>is loading</h2>; } if (error || !Array.isArray(data)) { return <h2>加载失败,请重试</h2>; } const definition = data[0]["meanings"][0]["definitions"][0]["definition"]; return definition; }; return ( <> {getDefinition()} <Button onClick={handleWordchange}>切换单词</Button> </> ); }; export default Word;
修复后点击按钮会立刻更新word状态,react-query识别到queryKey变化后自动拉取对应单词的释义,无需多次点击,请求完成后页面会自动渲染最新内容。
内容的提问来源于stack exchange,提问作者flowoverstack
相关产品推荐
相关产品推荐

