2017-09-18 25 views
0

我将一个graphql api调用与一个数组修改相结合。无法添加/删除密封阵列元素

async deletePhoto(photoId, driveId, index) { 

    this.property.photos.splice(index, 1); 

    await api.photos.remove(this.property.id, photoId, driveId); 
}, 

API调用:

const remove = async (propertyId, photoId, driveId) => { 

    const mutation = gql` 
    mutation photoDelete($propertyId: Int!, $photoId: String!, $driveId: String!) { 
     deletePropertyPhoto(propertyId: $propertyId, photoId: $photoId, driveId: $driveId) 
    } 
    `; 

    const result = await apolloClient.mutate({ 
    mutation, 
    variables: { 
     propertyId, 
     photoId, 
     driveId, 
    }, 
    }); 

    console.log(result); 
    return result; 
}; 

问题:

Uncaught (in promise) TypeError: Cannot add/remove sealed array elements 
    at Array.splice (<anonymous>) 
    at VueComponent._callee3$ (http://localhost:3030/_nuxt/3.js:284:38) 
    at tryCatch (http://localhost:3030/_nuxt/vendor.bundle.5559a1f55cb4b1323e8d.js:26549:40) 
    at Generator.invoke [as _invoke] (http://localhost:3030/_nuxt/vendor.bundle.5559a1f55cb4b1323e8d.js:26787:22) 
    at Generator.prototype.(anonymous function) [as next] (http://localhost:3030/_nuxt/vendor.bundle.5559a1f55cb4b1323e8d.js:26601:21) 
    at step (http://localhost:3030/_nuxt/vendor.bundle.5559a1f55cb4b1323e8d.js:8714:30) 
    at http://localhost:3030/_nuxt/vendor.bundle.5559a1f55cb4b1323e8d.js:8732:14 
    at Promise (<anonymous>) 
    at F (http://localhost:3030/_nuxt/vendor.bundle.5559a1f55cb4b1323e8d.js:8036:28) 
    at VueComponent.<anonymous> (http://localhost:3030/_nuxt/vendor.bundle.5559a1f55cb4b1323e8d.js:8711:12) 

是什么让这个错误如此怪异?当我删除api调用时,它工作正常。这对我来说没有任何意义,因为api调用与数组修改无关。

编辑: 这是疯了,有时会出现错误,有时拼接工作得很好。这是我遇到过的最随机的错误。

EDIT2: 当读取性能(和照片),我已经取得了graphql结果的对象复制:

async asyncData({ params }) { 
    const fetchedProperty = await api.properties.findOne(params.id); 
    return { 
     oldProperty: fetchedProperty, 
     property: Object.assign({}, fetchedProperty), 
    }; 
    }, 
+0

据我所知,graphql总是返回一成不变的结构,无论是你应该保持它不变,或者使它们的结构副本做可变的结构 –

+0

@EvaldoBratti我明白,但正如你所看到的,我没有修改api调用的结果。甚至在api通话之前。除此之外,当我第一次拿到照片时,我已经做了一个副本。请看EDIT2。 – Soundwave

+0

是的,'this.property'是通过api调用设置的。您使用Object.assign'浅拷贝对象,但设置为'photos'的数组仍然是密封的。如果要在'deletePhoto'方法中编辑这些值,则需要在设置'property'时明确复制'fetchedProperty.photos' – thanksd

回答

0

你的API调用显然与一个返回一个对象(fetchedPropertyphotos已通过Object.seal密封的阵列。

您正在将property数据属性设置为Object.assign({}, fetchedProperty),该属性将fetchedProperty中每个属性的值分配给空数组。

这仍然意味着photos(它是一个密封阵列)的值被设置为分配给您的property数据属性的空对象。

您需要明确复制photos数组的值,并将其设置为data属性的photos属性。也许是这样的:

async asyncData({ params }) { 
    const fetchedProperty = await api.properties.findOne(params.id); 
    let property = Object.assign({}, fetchedProperty); 
    let property.photos = [...fetchedProperty.photos]; 

    return { 
    oldProperty: fetchedProperty, 
    property: property 
    }; 
} 
0

另一种方法来删除一个密封对象是使用slice

this.property.photos = this.property.photos.slice(0, idx).concat(this.property.photos.slice(idx + 1)); 

在你的函数为:

async deletePhoto(photoId, driveId, index) { 
    this.property.photos = this.property.photos.slice(0, idx).concat(this.property.photos.slice(idx + 1)); 
    await api.photos.remove(this.property.id, photoId, driveId); 
},