咨询修复Apollo useQuery钩子渲染错误:依赖查询结果的调用问题
修复useQuery依赖前置数据导致的渲染错误
问题场景
当前使用3个useQuery钩子,其中OSData查询的变量NUMBER依赖于GET_Ram和GET_Hardware查询生成的UniqueList。直接调用OSData查询会出现变量未定义问题,延后调用又触发Hook渲染错误,需解决这一矛盾。
原代码示例:
const { data: OSData, error: OSError, loading: OSLoading, } = useQuery(OSData, { // 注:此处第一个参数应为查询键(如'GET_OS')或查询函数,原代码可能存在笔误 variables: { NUMBER: UniqueList, }, }) const { data: RamData, error: RamERROR, loading: RamLOADING, } = useQuery(GET_Ram) const { data: Hardware, error: HardwareERROR, loading: HardwareLOADING, } = useQuery(GET_Hardware)
解决方案
1. 使用enabled参数控制查询触发时机
React Query的useQuery内置了enabled选项,仅当该值为true时才会执行查询。我们可以通过判断RamData、Hardware是否就绪,以及UniqueList是否已生成,来决定是否启用OSData查询:
// 先获取Ram和Hardware数据 const { data: RamData, error: RamERROR, loading: RamLOADING, } = useQuery(GET_Ram) const { data: Hardware, error: HardwareERROR, loading: HardwareLOADING, } = useQuery(GET_Hardware) // 生成UniqueList(假设这里是基于RamData和Hardware的处理逻辑) const UniqueList = useMemo(() => { if (!RamData || !Hardware) return [] // 此处替换为实际生成UniqueList的逻辑 return [...new Set([...RamData.items, ...Hardware.items])] }, [RamData, Hardware]) // 仅当UniqueList有效时,才执行OSData查询 const { data: OSData, error: OSError, loading: OSLoading, } = useQuery('GET_OS', { // 修正查询键为合理值 variables: { NUMBER: UniqueList, }, enabled: UniqueList.length > 0 && !RamLOADING && !HardwareLOADING })
2. 用useQueries批量管理前置查询
如果GET_Ram和GET_Hardware是并行执行的,可以用useQueries批量获取这两个数据,统一判断就绪状态:
const [RamResult, HardwareResult] = useQueries([ { queryKey: 'GET_Ram', queryFn: GET_Ram }, { queryKey: 'GET_Hardware', queryFn: GET_Hardware } ]) const { data: RamData, loading: RamLOADING } = RamResult const { data: Hardware, loading: HardwareLOADING } = HardwareResult const UniqueList = useMemo(() => { if (!RamData || !Hardware) return [] // 实际生成逻辑 return [...new Set([...RamData.items, ...Hardware.items])] }, [RamData, Hardware]) const { data: OSData, error: OSError, loading: OSLoading, } = useQuery('GET_OS', { variables: { NUMBER: UniqueList }, enabled: !RamLOADING && !HardwareLOADING && UniqueList.length > 0 })
3. 手动触发查询(useQueryClient)
如果需要更灵活的控制逻辑,可以使用useQueryClient的fetchQuery方法,在useEffect中监听前置数据的变化,手动触发OSData查询:
const queryClient = useQueryClient() const { data: RamData, loading: RamLOADING, } = useQuery(GET_Ram) const { data: Hardware, loading: HardwareLOADING, } = useQuery(GET_Hardware) const UniqueList = useMemo(() => { if (!RamData || !Hardware) return [] // 实际生成逻辑 return [...new Set([...RamData.items, ...Hardware.items])] }, [RamData, Hardware]) // 存储OSData的状态 const [OSData, setOSData] = useState(null) const [OSLoading, setOSLoading] = useState(false) const [OSError, setOSError] = useState(null) useEffect(() => { // 前置数据未就绪时不执行 if (RamLOADING || HardwareLOADING || UniqueList.length === 0) return const fetchOSData = async () => { setOSLoading(true) try { const data = await queryClient.fetchQuery('GET_OS', { variables: { NUMBER: UniqueList } }) setOSData(data) } catch (err) { setOSError(err) } finally { setOSLoading(false) } } fetchOSData() }, [RamLOADING, HardwareLOADING, UniqueList, queryClient])
关键注意点
- 确保
UniqueList的生成逻辑使用useMemo缓存,避免不必要的重计算和查询触发。 - 原代码中
useQuery(OSData, ...)的第一个参数应为查询键(字符串/数组)或查询函数,需修正为正确值,否则会导致查询逻辑异常。
内容的提问来源于stack exchange,提问作者user18175092
相关产品推荐
相关产品推荐

