React Query中如何判断查询视图状态、按需更新及获取视图查询列表?
判断查询是否处于视图及获取活跃查询列表的实用方案
一、判断单个查询是否在视图中(无需全局状态)
1. 针对“查询被组件活跃使用”的场景
如果用的是React Query这类查询管理库,可直接通过查询实例的isActive状态判断——该状态为true时,说明当前有组件在订阅该查询(即对应组件处于挂载/活跃状态)。
代码示例:
import { useQueryClient } from '@tanstack/react-query'; // 在组件或逻辑中 const queryClient = useQueryClient(); const isXQueryActive = queryClient.getQueryState('x')?.isActive; // 仅当活跃时触发更新 if (isXQueryActive) { queryClient.refetchQueries(['x']); }
2. 针对“组件在浏览器视口内可见”的场景
若要精准判断组件是否在用户可视区域,用Intersection Observer API即可,无需全局状态,每个组件独立管理可视状态:
import { useEffect, useState, useRef } from 'react'; import { useQuery } from '@tanstack/react-query'; function XQueryComponent() { const [isInViewport, setIsInViewport] = useState(false); const componentRef = useRef(null); useEffect(() => { const observer = new IntersectionObserver( ([entry]) => setIsInViewport(entry.isIntersecting), { threshold: 0.1 } // 可视占比达10%时判定为在视图中,可按需调整 ); if (componentRef.current) observer.observe(componentRef.current); return () => observer.disconnect(); }, []); // 仅在视图中时自动刷新查询 const { data } = useQuery({ queryKey: ['x'], queryFn: fetchXData, refetchInterval: isInViewport ? 3000 : false, // 可视时每3秒刷新,否则停止 }); return <div ref={componentRef}>{/* 渲染查询内容 */}</div>; }
二、获取处于视图中的查询列表
1. 获取所有活跃订阅的查询列表
利用React Query的API,通过getQueries()拿到所有查询实例,再筛选出isActive为true的:
import { useQueryClient } from '@tanstack/react-query'; const queryClient = useQueryClient(); const activeQueries = queryClient.getQueries().filter(q => q.state.isActive); const activeQueryKeys = activeQueries.map(q => q.queryKey); // activeQueryKeys即为当前被组件活跃使用的查询键列表
2. 获取视口内可见的查询列表
用React Context管理可视查询集合,比全局状态更优雅:
// 第一步:创建Context管理可视查询 import { createContext, useContext, useState } from 'react'; const VisibleQueriesContext = createContext({ addKey: () => {}, removeKey: () => {}, visibleKeys: new Set() }); export function VisibleQueriesProvider({ children }) { const [visibleKeys, setVisibleKeys] = useState(new Set()); const addKey = (key) => { setVisibleKeys(prev => new Set([...prev, key])); }; const removeKey = (key) => { setVisibleKeys(prev => { const newSet = new Set(prev); newSet.delete(key); return newSet; }); }; return ( <VisibleQueriesContext.Provider value={{ addKey, removeKey, visibleKeys }}> {children} </VisibleQueriesContext.Provider> ); } // 第二步:在查询组件中注册可视状态 export function XQueryComponent() { const { addKey, removeKey } = useContext(VisibleQueriesContext); const componentRef = useRef(null); useEffect(() => { const observer = new IntersectionObserver(([entry]) => { entry.isIntersecting ? addKey('x') : removeKey('x'); }); if (componentRef.current) observer.observe(componentRef.current); // 组件卸载时清理 return () => { observer.disconnect(); removeKey('x'); }; }, [addKey, removeKey]); return <div ref={componentRef}>{/* 内容 */}</div>; } // 第三步:在需要获取列表的地方使用 export function QueryStatusComponent() { const { visibleKeys } = useContext(VisibleQueriesContext); return ( <div> 当前可视查询:{Array.from(visibleKeys).join(', ')} </div> ); }
内容的提问来源于stack exchange,提问作者Siva rama krishna Bethu
相关产品推荐
相关产品推荐

