Description
Describe the bug
I took me a while to understand what's going on here, this happens due to me using freezeResults: true
When using this with apollo composable the frozen results also freeze the reactive internals (deps, subs and so on)
This causes errors where in some cases vue tries to modify them, here how I replicated it:
I have 3 components, I stripped them down to the bare minimum
root component:
<template>
<div>
<div v-if="isLoading">
Spells are loading
</div>
<SpellCompStriped v-for="spell in spellsByPage[currentPage]" v-else :key="spell.id" :spell="spell" />
</div>
</template>
<script lang="ts">
import { reactive, toRefs } from 'nuxt-composition-api'
import { chunk } from 'lodash-es'
import { reactiveSpells } from '~/apollo/sharedQueries/getSpells'
import SpellCompStriped from '~/components/shared/spells/SpellCompStriped.vue'
type SpellPageState = {
spellsByPage: Array<any[]>,
isLoading: boolean,
currentPage: number
}
export default {
name: 'Spells',
components: { SpellCompStriped },
setup () {
const state = reactive<SpellPageState>({
spellsByPage: [],
currentPage: 0,
isLoading: true,
})
const allSpells = reactiveSpells()
allSpells.onResult((result) => {
const spell = result!.data.data.spells[0]
state.spellsByPage = chunk([{ id: spell.id, cast: spell.cast], 10) /issue lays here
state.isLoading = false
})
return toRefs(state)
},
}
</script>
SpellComp:
<template>
<div class="d-flex flex-column flex-grow-1">
<div class="d-flex flex-grow-1" @click="expand = !expand">
click
</div>
<Cast v-if="expand" :cast="spell.cast" />
</div>
</template>
<script lang="ts">
import Cast from '~/components/shared/spells/properties/Cast.vue'
export default {
components: { Cast },
props: {
spell: {},
},
data () {
return { expand: false }
},
}
</script>
<style lang="sass" scoped>
</style>
<template>
<div v-if="cast" title="Cast" />
</template>
<script lang="ts">
export default {
props: {
cast: {},
},
}
</script>
<style lang="sass">
.action-icon
height: 20px
width: auto
svg
vertical-align: middle
</style>
Cast component
this renders fine, When clicking on the SpellComp div and enabling the render of the Cast component this error shows up:
client.js:96 TypeError: Cannot add property 0, object is not extensible
at Array.push (<anonymous>)
at Dep.addSub (vue.common.dev.js:718)
This occurs because the subs array is Frozen
Now, how to fix this?
if you go to the main component to the onResult event, and spread the cast
property like so:
state.spellsByPage = chunk([{ id: spell.id, cast: { ...spell.cast } }], 10)
this fixes the issue,
This has nothing to do with the cast property being frozen as doing this:
state.spellsByPage = chunk([{ id: spell.id, cast: Object.freeze({ ...spell.cast }) }], 10)
Also solves the issue
By spreading the cast property we are extracting it from the proxy and making it not reactive anymore, this for some reason solves the issue, I have no idea what is going on and how this effects the subs array in the component