Apollo Client State异常:resetStore后writeData无法写入Simulation对象
问题分析与解决方案
我帮你排查下这个问题——你在调用client.resetStore()后恢复本地状态时,Simulation相关的数据没能正确写入缓存,根源在于对象类型的本地状态需要同时维护实体数据和查询引用,而你之前的操作只更新了查询引用,没补上实体本身。
为什么pageTitle正常,Simulation失败?
pageTitle是标量类型(null/字符串),写入时直接存在ROOT_QUERY下,不需要额外的实体存储。Simulation是自定义对象类型,Apollo Client的缓存采用归一化存储:初始化时会在缓存中生成一个$ROOT_QUERY.simulation的实体ID,把Simulation的数据存在这个ID下,同时在ROOT_QUERY里存一个指向该ID的引用。resetStore()会把这两部分都清空,你之前的writeData/writeQuery只更新了ROOT_QUERY的引用,没重建对应的实体,导致查询时找不到数据。
修复方案
方法一:手动重建实体+更新查询引用
直接操作缓存,先写入Simulation实体,再更新ROOT_QUERY的引用,保持和初始化时的结构一致:
// 在resetStore完成后执行 const cache = client.cache; const simulationRootId = "$ROOT_QUERY.simulation"; // 和初始化时生成的ID保持一致 // 第一步:写入Simulation实体到缓存 cache.writeFragment({ id: simulationRootId, fragment: gql` fragment SimulationData on Simulation { __typename configurationName job status uuid } `, data: { __typename: 'Simulation', configurationName: null, job: null, status: null, uuid: null, }, }); // 第二步:更新ROOT_QUERY中的simulation引用,同时设置pageTitle client.writeData({ data: { simulation: { __typename: 'Simulation', id: simulationRootId, // 关联到刚才写入的实体ID configurationName: null, job: null, status: null, uuid: null, }, pageTitle: 'test', }, });
方法二:复用初始化逻辑(更简洁)
把本地状态的默认值初始化逻辑抽成函数,在resetStore后重新执行:
// 抽离初始化本地默认值的函数 const initializeLocalState = (cache) => { cache.writeData({ data: { simulation: { __typename: 'Simulation', configurationName: null, job: null, status: null, uuid: null, }, pageTitle: null, }, }); }; // 初始化客户端时调用(和withClientState的defaults保持一致) const stateLink = withClientState({ cache, defaults: { simulation: { __typename: 'Simulation', configurationName: null, job: null, status: null, uuid: null, }, pageTitle: null, }, resolvers: {}, }); initializeLocalState(cache); // 登出时重置缓存并重新初始化 client.resetStore().then(() => { initializeLocalState(client.cache); // 再单独设置pageTitle为test client.writeData({ data: { pageTitle: 'test' } }); });
执行以上任意一种方案后,缓存结构会恢复到你清除前的状态,Simulation相关的查询就能正常工作了。
内容的提问来源于stack exchange,提问作者mblichar
相关产品推荐
相关产品推荐

