如何为Apollo Client查询结果注入唯一标识符id?
为Apollo Client查询结果注入自定义唯一ID以修复缓存问题
当查询返回的car_view对象没有原生唯一ID时,可以通过以下几种方式在Apollo Client中注入自定义ID,确保缓存正常工作:
方法一:通过dataIdFromObject生成唯一缓存ID
在创建Apollo Client实例时,配置InMemoryCache的dataIdFromObject函数,利用现有字段(如brand和year)组合生成唯一ID:
import { ApolloClient, InMemoryCache } from '@apollo/client'; const client = new ApolloClient({ uri: '/graphql', cache: new InMemoryCache({ dataIdFromObject: (object) => { if (object.__typename === 'car_view') { // 用brand和year拼接成唯一ID,需确保该组合无重复 return `car_view:${object.brand}:${object.year}`; } // 其他类型沿用默认逻辑(优先使用id/_id,否则用类型名) return object.id || object._id || object.__typename; }, }), });
该函数会为每个缓存对象生成唯一标识,Apollo Client将以此识别重复对象,正确维护缓存。
方法二:使用字段策略(Field Policies)注入ID
通过typePolicies配置,在写入缓存时为car_view对象添加自定义ID,并指定该ID为缓存的唯一标识:
const cache = new InMemoryCache({ typePolicies: { Query: { fields: { cars: { merge(existing, incoming) { // 为每个车辆项添加自定义ID,若brand+year可能重复,可追加数组索引确保唯一 return incoming.map((car, index) => ({ ...car, id: `${car.brand}:${car.year}:${index}` })); }, }, }, }, car_view: { // 指定使用自定义的id字段作为缓存唯一标识 keyFields: ['id'], }, }, });
这种方式更灵活,适合需要对特定查询结果做定制化处理的场景。
方法三:手动处理查询结果并更新缓存
在组件中通过useQuery的onCompleted回调,手动为返回的车辆项添加ID后更新缓存:
import { useQuery, gql } from '@apollo/client'; const GET_CARS = gql` query GetCars { cars: car_view { brand, year } } `; function CarsComponent() { const { data, client } = useQuery(GET_CARS, { onCompleted: (result) => { const carsWithId = result.cars.map(car => ({ ...car, __typename: 'car_view', id: `${car.brand}:${car.year}` })); // 将处理后的数据写入缓存 client.writeQuery({ query: GET_CARS, data: { cars: carsWithId } }); } }); // 渲染逻辑 return ( <div> {data?.cars?.map(car => ( <div key={car.id}>{car.brand} - {car.year}</div> ))} </div> ); }
这种方式需要手动干预,适合临时或局部场景,推荐优先使用前两种配置化方案。
内容的提问来源于stack exchange,提问作者Mammad Mammadli
相关产品推荐
相关产品推荐

