What could be causing the lack of updates for a watched object in vue?

Although there are many similar questions on this topic, mine has a unique twist. After delving into reactivity in depth, I feel like I have a solid grasp of the concept. However, one thing continues to baffle me:

Summary:

Why does a watched property detect changes when initialized using

currentValue = Object.assign({}, currentValue, initValue)
, but not with a straightforward assignment like currentValue = initValue;?

I have an object called scoreRules registered on the model of my Vue component.

In the mounted hook,

  1. I reset the model's scoreRules by doing this:

this.$data.scoreRules = initScoreRules;

(I'm using initScoreRules as a prop which is locally declared below for this question).

  1. I watch for changes in scoreRules and log "score has been changed" whenever the object changes.

This code snippet illustrates the scenario:

new Vue({
  el: '#app',
  data() {
    return {
      scoreRules: {
        type: 'number',
        minimum: null,
        maximum: null
      }
    }
  },
  mounted() {
  let initScoreRules = {type: 'number'};
    this.$data.scoreRules = initScoreRules;
    this.$watch('scoreRules', ()=>{console.log("score has been changed")}, {deep: true});
  }
});
<html>

<head>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.2.6/vue.js"></script>
</head>

<body>
  <div id="app">
    <span>Minimum score</span>
    <input type="number" name="minimumScore" v-model.number="scoreRules.minimum" />
</body>

</html>

When typing in the input field, the watch doesn't capture this change and nothing gets logged to the console.

If I then reinitialize scoreRules using

this.$data.scoreRules = Object.assign({}, this.$data.scoreRules,  initScoreRules);

new Vue({
  el: '#app2',
  data() {
    return {
      scoreRules: {
        minimum: null
      }
    }
  },
  mounted() {
    let initScoreRules = {};
    this.$data.scoreRules = Object.assign({}, this.$data.scoreRules,  initScoreRules);
    this.$watch('scoreRules', () => {
      console.log("score has been changed")
    }, {
      deep: true
    });
  }
});
<html>

<head>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.2.6/vue.js"></script>
</head>

<body>
  <div id="app2">
    <span>Minimum score</span>
    <input type="number" v-model.number="scoreRules.minimum" />
  </div>
</body>

</html>

The changes are now detected and recorded in the console. But why? My suspicion is that it relates to the inner workings of JavaScript itself, although the exact mechanism still eludes me.

Answer №1

The original object initially had the properties minimum and maximum. However, in the mounted lifecycle hook, you did the following:

let initScoreRules = {type: "number"};
this.$data.scoreRules = initScoreRules;

As a result, the scoreRules object no longer contains those properties.

In Vue, changes can only be observed for properties that are either:

  • defined in the data() method (which was initially done but then reverted in mounted)
  • set using Vue.set() / this.$set()
  • present on an object assigned to a reactive property

This last point is also why the second example functions as expected. In this case, you essentially do this (omitting the use of Object.assign for clarity):

this.$data.scoreRules = { minimum: null }; 

This new property will now be reactive.

To learn more about this topic, visit:

https://v2.vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Guide on inserting a dropdown menu following a specific count of <li> elements using Javascript or Jquery

I am currently working on an HTML project <div class="ktmsg"> <ul> <li class="a1"> <a title="Link Tools" href="#"> … </a> </li> <li class="a2"> <a title="Link Tools" href="#"> ...

What are the steps to incorporate ThreeJS' FontLoader in a Vue project?

I am encountering an issue while attempting to generate text in three.js using a font loader. Despite my efforts, I am facing difficulties in loading the font file. What could be causing this problem? const loader = new FontLoader(); loader.load( ' ...

Exploring methods to conduct testing on an AngularJS application using AngularJS end-to-end testing, specifically focusing on scenarios involving multiple inputs

Our program includes a directive that is repeated multiple times with an input field. The structure of our code resembles the following: <li> <label>AMI</label> <div class="searchbox" searchbox="" filter="search.ami"> ...

Permanently dismiss Bootstrap 4 alert using a cookie

Recently, I came across a bootstrap 4 alert that I found quite useful. Here is the code snippet for it: <div class="alert alert-warning alert-dismissible fade show" role="alert"> <button type="button" class="clo ...

What is the best way to incorporate an icon as a label in a Vuetify select dropdown menu?

I'm exploring Vue/Vuetify for the first time and I am currently working on implementing a select option feature on a website. Instead of using text labels, I would like to use icons as labels, similar to the image provided below. I am unsure if this i ...

Executing a time-consuming function call within the componentDidMount lifecycle method of a React component

When working with my React component, I utilize the componentDidMount function to pass a string received through props to a processing function. This function then returns another string which is used to update the component's state. import React, { C ...

Angular 4 - The Promising Outcome: How to Retrieve the Value upon Completion

Is there a way to retrieve a value from a promise and store it in a global variable? I've been attempting to accomplish this, but the global variable remains undefined. import { Injectable } from '@angular/core'; import {ActivatedRouteSnap ...

Pressing a button meant to transfer text from a textarea results in the typed content failing to show up

Having trouble with a custom text area called a math field. I'm currently interning on a project to build a math search engine, where users can input plain text and LaTeX equations into a query bar. The issue I'm facing is that sometimes when th ...

Dealing with ParseInt NaN problems in your code: a comprehensive guide

I have a code where I am trying to calculate the sum of input values. It works fine when numbers are entered, but if any input field is cleared, it shows total as NaN. I understand that using parseInt for number value is causing this issue, but without usi ...

Tips on implementing JSON data into select2 plugin

I have been trying to integrate the select2 plugin into my project. I followed a tutorial from this link, but unfortunately, it's not functioning properly for me. Here is the JSON output: [ {"ime":"BioPlex TM"}, {"ime":"Aegis sym agrilla"}, ...

What is the best way to access elements and attributes from a specific JSON file?

Is there a way to access each property within the JSON data provided? Additionally, I am interested in filtering specific objects based on their IDs. How can this be achieved using the array.filter method in JavaScript? { "records": [ ...

Validator alert for AMP scripts

I have implemented the amp version for my content management system. Since each article has a different body, some include amp-instagram while others include amp-facebook, and so on. In order to cover all bases, I have added both amp-facebook and amp-inst ...

What is the best way to include the ID in a Vue.js Ajax request for posts?

Is there a way to pass an "id" obtained as data in vue js? The id is coming as "agnt.basic.actor". Considering the presence of multiple ids, how can I achieve this? <tr v-for="agnt in agentlist"> <td v-if="agnt.basic">{{agnt.basic.actor}}< ...

Issue with setting state in useEffect causing an infinite loop due to either linter warning or user error

In its current state, my component appears as follows: const { listOfStuff = [{name:"john"},{name:"smith"}] } = props const [peopleNames, setPeopleNames] = useState([]) useEffect(() => { listOfStuff.forEach(userName => { setPeopleNames(people ...

What methods does Enzyme have for determining the visibility of components?

I am facing an issue with a Checkbox component in my project. I have implemented a simple functionality to hide the checkbox by setting its opacity : 0 based on certain conditions within the containing component (MyCheckbox) MyCheckBox.js import React fr ...

The tooltip in nvd3 is displaying the index instead of the label

I'm encountering an NVD3 tooltip issue with my multichart (multiline chart). The XAxis labels are set as JAN, FEB, MAR... DEC. However, when I hover over the graph, it displays 0, 1, 2, 3... 11 as the tooltip title instead of the month names. Here is ...

Excessive calls to the component update in React with Javascript are leading to application crashes

componentDidUpdate() { // Retrieving trades from the database and syncing with MobX store axios.get(`http://localhost:8091/trade`) .then(res => { this.props.store.arr = res.data; }) } After implementing this code, my ...

Sticky positioning with varying column widths

How can I create HTML and CSS columns that stick together without manually specifying the "left:" parameter every time? The current example in the fiddle achieves what I want, but requires manual setting of the "left:" value. Is there a way to make this m ...

I am experimenting with an express middleware that can either return next() or next("route")

After developing a middleware function that returns next() if a route's parameters are defined by queryItems, I came across a useful tool called node-mocks-http. However, it does not fake the next object. This led me to explore how this can be achieve ...

Having trouble with React JS BrowserRouter not routing correctly when used with Express JS and Nginx proxy

I am facing an issue where I need to send parameters to a React component through the URL. This works perfectly fine when I test it in my localhost development environment. However, the problem arises when I deploy the React app to my live server (). The ...