You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React+Apollo中ProgressBar调用refetch如何避免MemoBox同步更新

问题根因

Apollo Client默认会全局共享相同查询+相同变量的缓存结果,任意一处触发该查询的refetch更新缓存后,所有订阅该查询的组件都会收到更新通知,所以MemoBox会跟随ProgressBar的刷新动作重渲染。

可选解决方案

方案1:MemoBox手动拉取一次数据,不订阅缓存更新

直接用Apollo Client实例手动查询一次数据,存在本地state,后续缓存更新不会触发组件重渲染,适合MemoBox完全不需要后续更新用户数据的场景:

import { useApolloClient } from '@apollo/client';
import { useState, useEffect } from 'react';

const MemoBox = () => {
  const {userId} = useParams<{userId: string}>();
  const client = useApolloClient();
  const [memoHtml, setMemoHtml] = useState('');

  useEffect(() => {
    if (!userId) return;
    client.query({
      query: USER_QUERY, // 替换为你实际的USER_QUERY定义
      variables: { uuid: userId }
    }).then(res => {
      if (res.data?.user?.memoHtml) {
        setMemoHtml(res.data.user.memoHtml);
      }
    })
  }, [userId, client]);

  if (!memoHtml) return null;
  return (
    <Memo dangerouslySetInnerHTML={{__html: memoHtml}} />
  )
}

方案2:给MemoBox的查询加select过滤,仅当依赖字段变化时重渲染

利用Apollo useQuery的select配置,仅提取MemoBox依赖的memoHtml字段,只要该字段值不变,就不会触发组件重渲染,适合后续可能需要更新memo内容的场景:

const MemoBox = () => {
  const {userId} = useParams<{userId: string}>();
  // 直接提取memoHtml,值不变时不会触发重渲染
  const { data: memoHtml } = useUserQuery({
    variables: { uuid: userId },
    skip: !userId,
    select: (data) => data.user?.memoHtml
  });

  if (!memoHtml) return null;
  return (
    <Memo dangerouslySetInnerHTML={{__html: memoHtml}} />
  )
}

方案3:ProgressBar的刷新不更新全局缓存

给ProgressBar的refetch指定no-cache策略,刷新结果不写入全局缓存,自然不会触发其他订阅该查询的组件更新:

import { useState } from 'react';
import {useInterval} from 'beautiful-react-hooks';

const ProgressBar = () => {
  const {userId} = useParams<{userId: string}>();
  const [percent, setPercent] = useState(0);
  const { refetch: refetchUser } = useUserQuery({
    variables: {uuid: userId},
    skip: !userId,
  });

  useInterval(() => {
    // 刷新结果不进全局缓存
    refetchUser({ fetchPolicy: 'no-cache' }).then(res => {
      if (res.data?.user?.percent) {
        setPercent(res.data.user.percent);
      }
    })
  }, 3000);

  return (
     <p>{percent}</p>
  )
}

选型建议

  • 若MemoBox不需要任何后续更新,优先选方案1
  • 若MemoBox的memo内容可能会被其他操作更新,优先选方案2
  • 若你不想修改MemoBox的逻辑,优先选方案3

内容的提问来源于stack exchange,提问作者user15375616

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 19:09:04