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

除useRef外,如何让react-query的onSuccess仅在首次成功时执行?

问题与解决方案:useQuery首次onSuccess仅执行一次的替代方案

问题描述

需要保留useQuery的标准行为,但要让一段代码仅在首次onSuccess回调中执行。已知可通过useRef实现,想了解其他替代方案。

无法1:1复现实际场景,但提供的示例里,点击按钮递增计数器后,计数器会被重置为100,原因是onSuccess执行了两次。

示例代码:

const [counter, setCounter] = useState(0);
const { data, isLoading } = useQuery(
  ["key"],
  () => {
    return axios.get("https://picsum.photos/200");
  },
  {
    onSuccess() { // 此处会执行两次
      setCounter(100);
      console.log("fetch");
    }
  }
);

return (
  <div className="App">
    <button
      onClick={() => {
        setCounter(counter + 1);
      }}
    >
      counter {counter}
    </button>
    {data?.data && "数据已加载"}
  </div>
);

替代方案

1. 结合useQuery的isSuccess状态与useEffect监听

通过useEffect监听isSuccess状态变化,仅在状态从false变为true时执行目标代码:

const [counter, setCounter] = useState(0);
const { data, isSuccess } = useQuery(
  ["key"],
  () => axios.get("https://picsum.photos/200"),
);

useEffect(() => {
  if (isSuccess) {
    setCounter(100);
    console.log("fetch");
  }
}, [isSuccess]);

注:若后续查询因失效、重新获取再次成功,只要isSuccess未从false切换回true,就不会重复执行。此方案已能避免示例中的重复重置问题。

2. 依赖查询data的初始赋值状态

判断data是否从undefined变为有值,结合useEffect监听data变化,仅在首次获取到数据时执行代码:

const [counter, setCounter] = useState(0);
const { data } = useQuery(
  ["key"],
  () => axios.get("https://picsum.photos/200"),
);

useEffect(() => {
  if (data) {
    setCounter(100);
    console.log("fetch");
  }
}, [data]);

核心逻辑:首次请求成功后data才会被赋值,后续重新获取时data会更新,但只要业务允许后续成功不触发代码,此方案即可满足需求。

3. 利用react-query的enabled控制(限无需后续重新获取场景)

通过enabled选项控制查询是否执行,首次成功后禁用查询,避免后续触发onSuccess:

const [counter, setCounter] = useState(0);
const [queryEnabled, setQueryEnabled] = useState(true);
const { data } = useQuery(
  ["key"],
  () => axios.get("https://picsum.photos/200"),
  {
    enabled: queryEnabled,
    onSuccess() {
      setCounter(100);
      console.log("fetch");
      setQueryEnabled(false);
    }
  }
);

注意:此方案会在首次成功后停止查询的后续执行,若需保留useQuery的标准行为(如后台刷新、失效重试),则不适用。

示例中onSuccess重复执行的原因

点击按钮更新counter会触发组件重新渲染,而react-query的设计是:组件重新渲染时,若查询已处于成功状态,会再次执行onSuccess回调,以保证组件状态与查询结果同步。这就是每次点击按钮后,计数器被重置为100的原因。

内容的提问来源于stack exchange,提问作者Alex Ironside

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 20:30:56