React/Apollo多组件动态调用useLazyQuery的实现问题
实现多组件独立调用查询的方案
你的核心需求是让每个组件实例拥有独立的查询状态与请求逻辑,只需利用React Hook的特性(每个组件调用Hook时会生成独立状态),结合组件props传递uuid即可实现。以下是具体实现步骤:
1. 保持Service层代码不变
你的queryIndicatorExecution Hook本身已经具备独立性,每次调用都会创建新的useLazyQuery实例,无需修改:
const QUERY_EXEUCUTE_QUERY_INDICATOR = gql` query executeQueryIndicator($uuid: ID!) { executeQueryIndicator(uuid: $uuid) { uuid messages { type text } values } } ` export const queryIndicatorExecution = () => { const [executeQueryIndicator, {called, loading, data}] = useLazyQuery( QUERY_EXEUCUTE_QUERY_INDICATOR,{fetchPolicy: 'no-cache'} ) return {executeQueryIndicator, called, loading, data} }
2. 改造子组件,接收uuid并独立执行查询
将子组件改为接收uuid作为props,并在组件内部根据自身uuid触发查询,每个组件实例会维护自己的loading、data状态:
import { useEffect } from 'react'; import { queryIndicatorExecution } from './path-to-your-service'; const IndicatorCard = ({ uuid }) => { const { executeQueryIndicator, called, loading, data } = queryIndicatorExecution(); // 组件挂载/ uuid变化时自动执行查询 useEffect(() => { executeQueryIndicator({ variables: { uuid } }); }, [uuid, executeQueryIndicator]); // 状态渲染逻辑 if (loading) return <div>加载中...</div>; if (!called || !data) return <div>未查询</div>; const indicatorData = data.executeQueryIndicator; return ( <div className="indicator-card"> <h4>指标ID: {indicatorData.uuid}</h4> <div className="messages"> {indicatorData.messages.map((msg, idx) => ( <p key={idx} className={`msg-${msg.type}`}>{msg.text}</p> ))} </div> <div className="values">数值: {indicatorData.values.join(', ')}</div> </div> ); }; export default IndicatorCard;
如果需要手动触发查询(比如点击按钮),可以去掉useEffect,改为按钮触发:
const IndicatorCard = ({ uuid }) => { const { executeQueryIndicator, called, loading, data } = queryIndicatorExecution(); return ( <div className="indicator-card"> <button onClick={() => executeQueryIndicator({ variables: { uuid } })} disabled={loading}> {loading ? '查询中...' : '执行查询'} </button> {loading && <div>加载中...</div>} {data && ( <> <h4>指标ID: {data.executeQueryIndicator.uuid}</h4> {/* 渲染数据逻辑 */} </> )} </div> ); };
3. 父组件动态渲染多实例
在父组件中传入不同的uuid,渲染多个独立的子组件:
import IndicatorCard from './IndicatorCard'; const IndicatorListPage = () => { // 假设这是从接口或状态中获取的uuid列表 const indicatorUuids = ['uuid1', 'uuid2', 'uuid3', 'uuid4']; return ( <div className="indicator-list"> {indicatorUuids.map(uuid => ( <IndicatorCard key={uuid} uuid={uuid} /> ))} </div> ); }; export default IndicatorListPage;
关键原理
React Hook的特性保证了:每个IndicatorCard组件实例调用queryIndicatorExecution时,都会创建独立的useLazyQuery状态(包括loading、data、executeQueryIndicator方法),因此多个组件之间的查询状态完全隔离,不会互相干扰。
内容的提问来源于stack exchange,提问作者Anthony
相关产品推荐
相关产品推荐

