如何在点击处理函数中通过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
相关产品推荐
相关产品推荐

