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

如何在点击处理函数中通过useSWR条件获取数据并单次触发目标函数?

解决方案

核心问题分析

你当前需要点击两次的原因是:useSWR是声明式Hook,默认在组件渲染阶段触发请求。第一次点击时才初始化useGetFullProduct并触发请求,此时数据还未返回;第二次点击时数据已经加载完成,才能执行myFn。要实现一次点击完成操作,需要让点击动作主动触发请求,并在请求完成后立即执行目标函数。

方案一:修改自定义Hook,支持手动触发+等待数据返回

调整useGetFullProduct,让它默认不自动发起请求,而是通过mutate手动触发,同时允许等待请求完成:

import useSWR from 'swr';

// 替换为你实际的数据获取逻辑
const fetcher = (url) => fetch(url).then(res => res.json());

export function useGetFullProduct() {
  // 初始不传请求key,关闭自动请求
  const { data: fullProduct, error, mutate } = useSWR(null, fetcher, {
    revalidateOnMount: false,
    revalidateOnFocus: false
  });

  // 封装触发请求并返回数据的方法
  const fetchFullProduct = async (productId) => {
    const data = await mutate(`/api/products/${productId}`);
    return data;
  };

  return { fullProduct, error, fetchFullProduct };
}

组件中点击处理函数的写法:

const { fetchFullProduct } = useGetFullProduct();

const handleClick = async (productId) => {
  const fullProduct = await fetchFullProduct(productId);
  if (fullProduct) {
    myFn(fullProduct);
  }
};

方案二:利用useSWR的onSuccess回调(无需await)

如果不想使用await,可以在触发请求时指定onSuccess回调,数据返回后自动执行myFn:

修改Hook:

export function useGetFullProduct() {
  const { data: fullProduct, error, mutate } = useSWR(null, fetcher, {
    revalidateOnMount: false,
    revalidateOnFocus: false
  });

  const fetchFullProduct = (productId, onSuccess) => {
    mutate(`/api/products/${productId}`, { onSuccess });
  };

  return { fullProduct, error, fetchFullProduct };
}

组件点击处理函数:

const { fetchFullProduct } = useGetFullProduct();

const handleClick = (productId) => {
  fetchFullProduct(productId, (fullProduct) => {
    if (fullProduct) {
      myFn(fullProduct);
    }
  });
};

关键原理

通过将useSWR的初始请求key设为null,关闭自动触发逻辑;然后通过mutate手动触发请求,利用mutate返回Promise的特性(或onSuccess回调),在数据返回后立即执行myFn,从而实现一次点击完成整个流程。

内容的提问来源于stack exchange,提问作者Roman T

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 04:52:18