Cristal
Cristal

Reputation: 502

Vue error Uncaught (in promise) RangeError: Maximum call stack size exceeded on updating computed value

Here is my code under computed

 computed: {
      display: {
        get() {
          return this.display
        },
        set(newValue) {
          this.display = newValue
        }
      }
    },

i am trying to update the value of computed from a function under model

async submit() {
        this.display = false;
}

while submit function runs, i get below error on console

Uncaught (in promise) RangeError: Maximum call stack size exceeded

Upvotes: 0

Views: 1423

Answers (1)

skirtle
skirtle

Reputation: 29092

When you write this.display = newValue in the set it will just cause the set to be called again, going round and round in a loop.

To wrap a prop in a computed property you need to give it a different name. Further, the set should be emitting an event so that the parent component can update the data. You can't do it directly within the current component.

The example below uses the sync modifier but you could use a separate event listener if you prefer.

const Child = {
  template: `<input v-model="displayModel">`,

  props: ['display'],
  
  computed: {
    displayModel: {
      get () {
        return this.display
      },
      
      set (display) {
        this.$emit('update:display', display)
      }
    }
  }
}

new Vue({
  el: '#app',
  
  components: {
    Child
  },
  
  data () {
    return {
      parentDisplay: 'hello'
    }
  }
})
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>

<div id="app">
  <p>{{ parentDisplay }}</p>
  <child :display.sync="parentDisplay"></child>
</div>

You could also just emit the event directly rather than modifying the property at all, skipping the computed property altogether. i.e. Replace this.display = false; with an $emit.

Alternatively, if the prop is used only to set the initial value of the property then you should just copy it across to a data property when the component is first created:

props: ['display'],

data () {
  return {
    internalDisplay: this.display
  }
}

You can then set the value of internalDisplay directly.

Upvotes: 3

Related Questions