ReactJS使用Apollo GraphQL订阅删除时报错:无法操作密封数组元素
解决Apollo GraphQL订阅中TypeError: Cannot add/remove sealed array elements的问题
我来帮你搞定这个错误!你遇到的这个问题主要有两个核心原因,咱们一步步拆解:
错误根源
- Apollo返回的数据是不可变密封的:Apollo Client为了保证缓存一致性,返回的
previousResult里的数组是被密封(sealed)的,你不能用splice这种原地修改原数组的方法操作它——splice会直接改动原数组,而密封对象不允许添加/删除元素,这就是报错的直接原因。 - updateQuery返回值结构错误:你的代码返回了
splice的结果,但splice返回的是被删除元素组成的数组,而updateQuery要求返回和previousResult结构完全一致的对象(也就是包含Posts字段的对象),不是直接返回数组。
修复后的代码
直接用filter创建新数组,同时保证返回正确的结构:
componentWillReceiveProps(nextProps) { if (!this.subscription && !nextProps.data.loading) { const { subscribeToMore } = this.props.data this.subscription = [subscribeToMore({ document: postDeleted, updateQuery: (previousResult, { subscriptionData }) => { const delPost = subscriptionData.data.postDeleted; // 用filter创建新数组,过滤掉被删除的帖子,完全不碰原密封数组 const updatedPosts = previousResult.Posts.filter(post => post.id !== delPost.id); // 返回和原结构一致的对象,Apollo才能正确更新缓存 return { ...previousResult, Posts: updatedPosts }; }, })] } }
额外提醒
- 现在React官方已经不推荐使用
componentWillReceiveProps了,如果是新项目或者可以重构的话,建议换成componentDidUpdate或者用函数组件配合useEffect来实现订阅逻辑。 - 记得在组件卸载时取消订阅,避免内存泄漏:
componentWillUnmount() { if (this.subscription) { this.subscription.forEach(sub => sub()); } }
内容的提问来源于stack exchange,提问作者s develop
相关产品推荐
相关产品推荐

