如何基于SWR返回的响应数据触发重新拉取请求
正确实现方案
现有代码的问题
- 直接在组件渲染逻辑中调用
setTimeout,会导致每次组件重渲染时只要目标字段不存在就创建新的定时器,最终出现大量重复请求、内存泄漏的问题 - 没有对定时器做清理逻辑,组件卸载后定时器仍然会触发请求
方案1:useEffect + 手动定时器控制
适合需要自定义复杂重试逻辑的场景,需要手动处理副作用清理:
import { useEffect, useRef } from 'react' const { data, mutate } = useSWR(key, fetcher) // 可选:添加最大重试次数限制,避免后端异常时无限轮询 const retryCountRef = useRef(0) const MAX_RETRY = 10 useEffect(() => { // 目标字段存在时直接返回,重置重试计数 if (typeof data?.someData !== "undefined") { retryCountRef.current = 0 return } // 超过最大重试次数停止轮询 if (retryCountRef.current >= MAX_RETRY) return const timer = setTimeout(() => { mutate() retryCountRef.current += 1 }, 1000) // 依赖变化/组件卸载时自动清理定时器 return () => clearTimeout(timer) }, [data, mutate])
方案2:SWR原生动态轮询配置(更推荐)
SWR的refreshInterval配置项支持传入函数,可直接根据返回的响应数据动态决定轮询间隔,返回0代表停止轮询。内部已经处理了定时器创建、清理、请求去重等逻辑,无需手动管理副作用:
const { data } = useSWR<IGetAnalysis>(key, fetcher, { // 目标字段不存在时1秒轮询一次,存在则停止轮询 refreshInterval: (data) => typeof data?.simularityJson.analyzes === "undefined" ? 1000 : 0, // 可选配置:请求出错时是否继续轮询 refreshWhenError: true, // 可选配置:页面切到后台时是否继续轮询 refreshWhenHidden: false })
内容的提问来源于stack exchange,提问作者Hyesung Oh
相关产品推荐
相关产品推荐

