apollo-client: disable maybeDeepFreeze

Hi, I have an issue with apollo-client using angular 4. I have a service fetching data from the server.

The thing is that in my component need to be able to add items to an array returned from the service. But I keep getting errors indicating that the object and the array inside of it are frozen.

After deeply looking into the package I’ve seen that the object is being frozen in dev mode using the util maybeDeepFreeze. How can I override it? disable it? or bypass it?

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 7
  • Comments: 22 (5 by maintainers)

Commits related to this issue

Most upvoted comments

https://github.com/apollographql/apollo-client/pull/3883 disables deep freezing; query results will be mutable in the next release. Thanks all!

i want disable frezee

I think there should be a way to disable freezing. In my use case I am using immer within my mutation update functions, but am unable to due to this object freezing.

Can this issue be re-opened and properly discussed?

Hi all - re-opening. We’re reconsidering the use of maybeDeepFreeze, and might remove it completely (making results mutable). Making sure state is immutable is great in a lot of cases, but the fact that we’re only locking things down in dev/test environments, and not in prod, doesn’t quite sit right. We’re not deep freezing in production because it’s expensive, but we also think it’s important to align dev and prod environments (as we don’t want to introduce hard to debug environment based issues). More details shortly - thanks!

@jbaxleyiii @stubailo I would really appreciate a quick reply on this issue, as it has really stuck my project. Any workaround I can do for now? any suggestions?

I think the best option is to allow configure in the client configuration rather to enable the freeze feature or not, and let the default to be true. This way if there is no need to change the data retrieved than it’s all remain the same.

@hwillson Thanks for reconsidering it. Any idea of when it will be implemented? This is a really needed fix.

This issue has been automatically marked as stale becuase it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions to Apollo Client!

If you need to alter the returned frozen data you could clone it before subscribing. One easy way would be to use Lodash’s cloneDeep (https://lodash.com/docs#cloneDeep).

apollo.watchQuery(...)
    .valueChanges
    .map(({ data }) => _.cloneDeep(data))
        .subscribe(
            data => {
                // This data will not be frozen.
            });

This is griefing me to no end. If you’ve got deeply nested edges that you need to merge during a subscribe you’ll want to kill yourself. I’m thinking there has to be some sort of helper functionality exported to help. Consider how unreasonable it is to add a pet below:

const prev = {
  people: {
    edges: [
      {
        node: {
          id: 'UGVyc29uOjE=',
          name: 'Dominic',
          status: 'suicidal',
          pets: {
            edges: [
              {
                node: {
                  id: 'UGV0OjE=',
                  personId: 'UGVyc29uOjE=',
                  type: 'dog',
                  name: 'Boris',
                },
              },
            ],
          },
        },
      },
    ],
  },
};

deepFreeze(prev);

const newEdge = {
  node: {
    id: 'UGV0OjI=',
    personId: 'UGVyc29uOjE=',
    type: 'cat',
    name: 'Clyde',
  },
};

// As far as I know, you have to do all of the below:

const personEdge = prev.people.edges.find(e => e.node.id === newEdge.node.personId);
const newPersonEdge = {
  ...personEdge,
  node: {
    ...personEdge.node,
    pets: {
      ...personEdge.node.pets,
      edges: [
        ...personEdge.node.pets.edges,
        newEdge,
      ],
    },
  },
};

const newPersonEdges = prev.people.edges.filter(e => e.node.id !== newPersonEdge.node.id).concat(newPersonEdge);
let newPrev = {
  ...prev,
  people: {
    ...prev.people,
    edges: newPersonEdges,
  },
};

This reminds me of callback hell. I call it: spreading hell