graphqlapollo-client

Updating Apollo client cache directly and not part of a mutation


I'm trying to get something working as part of a proof of concept project and essentially want to be able to run a query that results in a bunch of objects being cached and then write directly to the cache to edit one of those objects.

For the purpose of this test I'm using the graphQL end point at https://github.com/trevorblades/countries

I'm fetching the countries initially, resulting in an array of 250 countries in the Apollo countries cache. Im then trying to updated the first one 'Andora' as follows:

client.writeQuery({
   query: gql`
     query WriteCountries($code: ID!) {
       countries(code: $code) {
         name
        }
      }`,
      data: { 
        countries: {
        __typename: 'Country',
        name: 'test'
      },
    },
      variables: {
        code: "AD"
      }
  });

This results in a second entry into the Apollo cache of countries({"code":"AD"}) with a single name key.

How can I instead ensure that the update gets applied to the entry in the original countries array?


Solution

  • Apollo doesn't know about relationship between countries without arguments, countries(code) and actual Country objects. Changes to Country objects will be reflected in other queries referencing them if those references can be established. Usually this means that you need an ID field for an object and request it in every query even if you don't need it. Then you can modify Country object directly via writeFragment

    client.writeFragment({
      id: 'Country:AD',
      fragment: gql`
        fragment MyCountry on Country {
          name        
        }
      `,
      data: {
        name: 'test',
      },
    });
    

    Country:AD should be the default internal id for the Apollo cache. If it is not the case replace this value with the correct id.

    This will affect the values of items inside the arrays returned by countries and countries(code) but not the arrays themselves. You need to manually modify both of them or add some custom read and merge functions if you wish to add/remove some Country objects or expect countries(code) to work for any given code.