Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to update or replace a cached entry's id with a new id in Apollo Client?

So I have a station in my app. Here's an example object:

interface Station {
  id: number; // auto-increment
  stationId: number; // this is a constant
  name: string;
  status: 'live' | 'draft';
}

When updating the station the stationId will never change, but sql will auto increment the id field. The station's status will also be updated to 'draft'. e.g.

const previousStation: Station = {
  id: 1,
  stationId: 123456,
  name: 'Example splet right',
  status: 'live',
}

// ... then some sql-fu

const nextStation: Station = {
  id: 2,
  stationId: 123456,
  name: 'Example spelt right',
  status: 'draft',
}

Apollo client is unable to infer that nextStation should replace previousStation, so there are a lot of mutations that require readQuery/ readFragment.

I was hoping there may be a simpler solution, but the complexity arises from the id changing. If I could find all references to its object-id in the normalised data cache and update those fields. Is something like this even possible?

like image 611
seedBoot Avatar asked Oct 23 '25 09:10

seedBoot


1 Answers

Solved. The key was to use a read/write fragment, using the old object-id, but passing in the new id as a reference. Then evict the old reference from the cache. It looked similar to this:

mutation({
    variables,

    update(cache, { data }) {
        if (!data) {
            return;
        }

        const { id: newId, __typename } = data.station;

        const existing = cache.readQuery({
            query: GET_STATION_QUERY,
            variables: { id: variables.id }
        });

        if (existing) {
            const newStation = {
                ...(existing.getStation || {}),
                ...(data.updateStation || {})
            };

            cache.writeQuery({
                query: GET_STATION_QUERY,
                variables: { id: newId },
                data: { station: newStation }
            });
        }

        const oldObjectId = `${__typename}:${variables.id}`;

        const fragment = gql`
            fragment MyFragment on SomeType {
                station {
                    id
                }
            }
        `;

        const existingStationOnMyType = cache.readFragment({
            id: oldObjectId,
            fragment
        });

        if (existingStationOnMyType) {
            cache.writeFragment({
                id: oldObjectId,
                fragment,
                data: {
                    id: newId
                }
            });

            cache.evict({ id: oldObjectId });
            cache.gc();
        }
    }
});
like image 148
seedBoot Avatar answered Oct 27 '25 04:10

seedBoot



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!