Why does Apollo/GraphQL return a non extensible object?
Asked Answered
R

4

9

I'm building an app with VueJS and I'm using Apollo client to fetch data from a database through a GrapgQL server. I have code that looks like this:

    apollo.query({
        query,
        variables
    })
    // context.commit('populateComments', payload) triggers the mutation
    .then(payload => context.commit('populateComments', payload))

Then, in my mutations I have the following

    populateComments: (state, payload) => { 
        state.comments = payload.data.comments
    }

When I try to push another object into the comments array in another mutation I get an error that reads "Cannot add property 300, object is not extensible". I have found that the following works

state.comments = Array.from(payload.data.comments)

But.. I'm not sure how effective it is to repeatedly copy large arrays like this? Is this the preferred way to do it?

Robbinrobbins answered 15/7, 2017 at 21:20 Comment(0)
T
0

Haven't worked with GraphQL/Apollo myself, but I guess it would hold to the principle of not mutating the data, hence the object not being extensible. What you can do in your mutations is to assign the data to the state like this:

Vue.set(state, 'comments', payload.data.comments)

This will make sure that the object is initially deep copied and afterwards updated in a Vue friendly way in order to support reactivity. You can read more here.

Tirzah answered 5/11, 2017 at 0:55 Comment(0)
G
0

Like you and Max I've faced the same problem and the only solution for me was to clone the object before

if you're using Lodash (https://lodash.com/docs/4.17.5#cloneDeep):

const commentsClone = _.cloneDeep(payload.data.comments)

if not (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign):

const commentsClone = Object.assign({}, payload.data.comments); 
Garish answered 25/2, 2018 at 16:41 Comment(1)
Object.assign will give you the same issue of your object/type is deeply nestedCaras
R
0

This should work:

const commentsClone = [...payload.data.comments];

Royceroyd answered 19/6, 2020 at 5:38 Comment(0)
D
-1

I've faced the exact same problem.

What I ended up doing is doing a _.cloneDeep before I send the data in to Vue commit.

Dillydally answered 9/11, 2017 at 3:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.