Skip to content

useQuery returns frozen refs not just frozen data #1028

Open
@gotenxds

Description

@gotenxds

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
image

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions