react-apollo 2.0.1中writeFragment无法更新缓存及UI问题求助
结合你提到的__typename缺失错误和当前无报错但缓存、UI不更新的情况,你可以按以下步骤逐一排查:
确保写入的数据包含正确的
__typename和唯一标识
Apollo缓存的核心依赖两个东西:__typename用来识别GraphQL类型,唯一ID(通常是id或_id)用来定位缓存中的具体对象。之前的__typename缺失错误说明你之前的数据里没这个字段,现在虽然没报错,但要确认你写入的数据里的__typename和你的GraphQL类型名完全一致,同时必须包含唯一ID。比如:// 正确的片段数据格式 const updatedData = { __typename: "User", // 要和你的GraphQL schema里的类型名完全匹配 id: "user_123", // 必须存在,用来定位缓存对象 status: "online" };如果你的类型用的是
_id而不是id,记得在ApolloClient配置里指定:const client = new ApolloClient({ cache: new InMemoryCache({ dataIdFromObject: obj => obj._id || obj.id // 优先用_id,没有再用id }), // 其他配置... });检查writeFragment的参数是否完全正确
这里最容易踩坑的是id参数的格式,必须是${__typename}:${唯一ID}的形式,而不是单纯的ID值。同时片段定义里必须包含__typename字段:// 先定义包含__typename的片段 const USER_STATUS_FRAGMENT = gql` fragment UserStatus on User { __typename id status } `; // 正确的writeFragment调用 client.writeFragment({ id: "User:user_123", // 注意格式:类型名+:+唯一ID fragment: USER_STATUS_FRAGMENT, data: updatedData });验证缓存是否真的被写入
别光看UI,先确认缓存里的数据是不是真的更新了:- 用Apollo DevTools(Chrome扩展)打开控制台的Apollo标签,找到对应的类型和对象ID,查看
status字段是否更新。 - 或者在代码里用
readFragment验证:const cachedUser = client.readFragment({ id: "User:user_123", fragment: USER_STATUS_FRAGMENT }); console.log("缓存中的用户数据:", cachedUser); // 看看status是不是online
- 用Apollo DevTools(Chrome扩展)打开控制台的Apollo标签,找到对应的类型和对象ID,查看
确认UI组件正确订阅了缓存数据
如果缓存更新了但UI没变化,大概率是组件没正确监听这个数据:- 如果你用
graphql高阶组件,确保组件的查询包含了status字段,并且查询的变量和缓存对象的ID匹配。 - 如果用
Query组件,也要保证查询的字段和writeFragment的片段一致,没有遗漏。 - 另外,别给查询设置
fetchPolicy: 'network-only',这种策略会跳过缓存直接请求网络,缓存更新自然不会反映到UI上。
- 如果你用
重新检查片段匹配器的配置
你说已经用了片段匹配,但react-apollo 2.0.x需要手动配置IntrospectionFragmentMatcher,如果配置不对,缓存还是无法正确识别片段类型:import { IntrospectionFragmentMatcher } from 'apollo-cache-inmemory'; // 这个fragmentTypes.json是通过apollo-codegen生成的,包含你的schema类型信息 import introspectionResult from './fragmentTypes.json'; const fragmentMatcher = new IntrospectionFragmentMatcher({ introspectionQueryResultData: introspectionResult }); const client = new ApolloClient({ cache: new InMemoryCache({ fragmentMatcher }), // 其他配置... });如果你还没生成
fragmentTypes.json,可以用apollo-codegen introspect-schema http://your-graphql-endpoint --output fragmentTypes.json命令生成。
内容的提问来源于stack exchange,提问作者FabioCosta

