无法添加/删除密封阵列元素
问题描述:
我将一个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),
};
},
答
你的API调用显然与一个返回一个对象(fetchedProperty
) photos
已通过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
};
}
答
另一种方法来删除一个密封对象是使用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);
},
据我所知,graphql总是返回一成不变的结构,无论是你应该保持它不变,或者使它们的结构副本做可变的结构 –
@EvaldoBratti我明白,但正如你所看到的,我没有修改api调用的结果。甚至在api通话之前。除此之外,当我第一次拿到照片时,我已经做了一个副本。请看EDIT2。 – Soundwave
是的,'this.property'是通过api调用设置的。您使用Object.assign'浅拷贝对象,但设置为'photos'的数组仍然是密封的。如果要在'deletePhoto'方法中编辑这些值,则需要在设置'property'时明确复制'fetchedProperty.photos' – thanksd