convoyinc/apollo-cache-hermes

writeFragment blows away entity's __typename

finnigantime opened this issue · 10 comments

Summary:

Say existingFoo is an entity in the cache with this data:

{
  __typename: 'Foo',
  id: '123',
  bar: oldBarValue,
  baz: 'bazValue'
}

We call writeFragment() to update it's .bar:

    proxy.writeFragment({
      id: existingFoo.id,
      fragment: fragments.fooWithBar,
      fragmentName: 'fooWithBar',
      data: {
        id: existingFoo.id,
        bar: newBarValue,
      },
    });

Expected Behavior:

{
  __typename: 'Foo',
  id: '123',
  bar: newBarValue,
  baz: 'bazValue'
}

Actual Behavior:

{
  __typename: undefined,
  id: '123',
  bar: newBarValue,
  baz: 'bazValue'
}

This happens when addTypename is true in the config since the fragment we are writing gets transformed and __typename gets added to it. If we don't similarly include __typename: 'Foo' in the data arg of writeFragment, the existingFoo.__typename gets deleted.

This is not obvious and at the least should result in a warning. Ideally it shouldn't happen at all (when writing a subfragment, I don't think __typename should be deleted if it wasn't specified on the subfragment). Recipes for writeFragment don't indicate the need to add __typename (https://www.apollographql.com/docs/angular/basics/caching#writequery-and-writefragment) and it has caused problems for users (https://stackoverflow.com/questions/48631954/apollo-writefragment-not-updating-data).

nevir commented
nevir commented
nevir commented
nevir commented

@nevir Yeah I think it's the latter. In this case the ID has not changed, we're persisting a small update to the existing entity.

nevir commented
nevir commented

I think really what you want here is for Hermes to support unvalidated writes (e.g. writeData)

nevir commented

Another potential option could be for hermes to assert that __typename is present in all nodes when addTypename is true

@nevir yeah I think writeData may be ideal. Spreading the existing object value makes sense and works, but this still seems like a gotcha since the cache supports partial fragment merging and the writeFragment examples don't suggest including __typename or ...existingFoo. I like the assertion idea. I was thinking of adding a warning around this.

nevir commented

FWIW, I'm pretty sure inmemory cache has the same behavior here