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

Apollo Client跨Query更新缓存问题:新增Feed无法同步至Screen B

问题说明

在Screen A创建Feed后,以下代码可成功更新seeAllFeeds查询的缓存,对应界面能即时刷新:

const updateUploadPhoto = (cache, result) => {
  const {
    data: { createFeed },
  } = result;
  if (createFeed.id) {
    cache.modify({
      id: "ROOT_QUERY",
      fields: {
        seeAllFeeds(prev) {
          return [createFeed, ...prev];
        },
      },
    });
  }
}

但Screen B使用的seeCertainUserFeedpoem查询无法同步新增Feed的信息,且受FlatList限制不能通过刷新解决(刷新会回到顶部)。

尝试两种方法均失败:

  1. 手动调用cache.modify匹配seeCertainUserFeedpoem数据:
const updateUploadPhoto = (cache, result) => {
    const {
      data: { createFeed },
    } = result;
    const FeedpomeId = `Feedpoem:${createFeed.id}`;
    const FeedpoemFragment = {
      caption: createFeed.caption,
      commentNumber: createFeed.commentNumber,
      createdAt: createFeed.createdAt,
      id: createFeed.id,
      isLiked: createFeed.isLiked,
      isMine: createFeed.isMine,
      likeNumber: createFeed.likeNumber,
      photos: createFeed.photos,
      poemCaption: null,
      poemCommentNumber: 0,
      poemLikeNumber: 0,
      poemTitle: null,
      updatedAt: createFeed.updatedAt,
    };
    if (createFeed.id) {
      cache.modify({
        id: "ROOT_QUERY",
        fields: {
          seeAllFeeds(prev) {
            return [createFeed, ...prev];
          },
        },
      });
      cache.modify({
        id: FeedpomeId,
        data: FeedpoemFragment,
      });
  
      navigation.navigate("Tabs", { screen: "일상" });
    }
  };
  1. 使用client.writeFragment时抛出错误:

LogBox.js:173 Possible Unhandled Promise Rejection (id: 0): Error: Cannot read properties of undefined (reading 'definitions') Error: Cannot read properties of undefined (reading 'definitions')

解决方案

方法1:同时更新ROOT_QUERY下的两个列表字段

需要在cache.modify中同时处理seeAllFeeds和seeCertainUserFeedpoem,并确保实体正确写入缓存:

import { gql } from '@apollo/client';

const updateUploadPhoto = (cache, result) => {
  const { data: { createFeed } } = result;
  if (!createFeed.id) return;

  // 同时更新两个查询的列表数据
  cache.modify({
    id: "ROOT_QUERY",
    fields: {
      seeAllFeeds(prev) {
        return [createFeed, ...prev];
      },
      // 处理特定用户的Feed列表
      seeCertainUserFeedpoem(prev, { args }) {
        // 匹配当前创建Feed的用户ID(根据你的实际查询参数调整)
        if (args.userId === createFeed.userId) {
          return [createFeed, ...prev];
        }
        return prev;
      }
    },
  });

  // 写入完整实体到缓存,确保后续查询能读取到
  cache.writeFragment({
    id: `Feedpoem:${createFeed.id}`,
    fragment: gql`
      fragment FeedpoemDetails on Feedpoem {
        caption
        commentNumber
        createdAt
        id
        isLiked
        isMine
        likeNumber
        photos
        poemCaption
        poemCommentNumber
        poemLikeNumber
        poemTitle
        updatedAt
        userId # 确保包含用户ID字段,用于匹配特定用户查询
      }
    `,
    data: createFeed,
  });

  navigation.navigate("Tabs", { screen: "일상" });
};

关键说明:

  • 必须在cache.modify中更新seeCertainUserFeedpoem字段,否则界面不会感知到列表新增项;
  • writeFragment需要传入gql解析的片段,而非纯对象,这是之前报错的核心原因;
  • 需确保createFeed包含userId(或匹配seeCertainUserFeedpoem查询参数的字段),用于判断是否需要更新该查询的列表。

方法2:直接写入特定查询结果

如果明确知道seeCertainUserFeedpoem的查询参数,可直接用writeQuery更新缓存:

import { gql } from '@apollo/client';

const updateUploadPhoto = (cache, result) => {
  const { data: { createFeed } } = result;
  if (!createFeed.id) return;

  // 更新seeAllFeeds
  cache.modify({
    id: "ROOT_QUERY",
    fields: {
      seeAllFeeds(prev) {
        return [createFeed, ...prev];
      },
    },
  });

  // 写入特定用户的Feed查询结果
  const targetUserId = createFeed.userId;
  const existingFeeds = cache.readQuery({
    query: gql`
      query seeCertainUserFeedpoem($userId: ID!) {
        seeCertainUserFeedpoem(userId: $userId) {
          caption
          commentNumber
          createdAt
          id
          isLiked
          isMine
          likeNumber
          photos
          poemCaption
          poemCommentNumber
          poemLikeNumber
          poemTitle
          updatedAt
        }
      }
    `,
    variables: { userId: targetUserId }
  })?.seeCertainUserFeedpoem || [];

  cache.writeQuery({
    query: gql`
      query seeCertainUserFeedpoem($userId: ID!) {
        seeCertainUserFeedpoem(userId: $userId) {
          caption
          commentNumber
          createdAt
          id
          isLiked
          isMine
          likeNumber
          photos
          poemCaption
          poemCommentNumber
          poemLikeNumber
          poemTitle
          updatedAt
        }
      }
    `,
    variables: { userId: targetUserId },
    data: {
      seeCertainUserFeedpoem: [createFeed, ...existingFeeds]
    }
  });

  navigation.navigate("Tabs", { screen: "일상" });
};
之前失败的原因分析
  1. 第一种方法:仅更新了实体数据,但未修改ROOT_QUERY下的seeCertainUserFeedpoem列表字段,界面订阅的是该列表,因此不会更新;
  2. 第二种方法:使用writeFragment时未传入合法的gql片段(仅传了纯对象),导致Apollo Client内部无法解析片段定义,抛出definitions未定义的错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 19:48:46