Reactivity in Vue 3 doesn't seem to be activated when called from within a class instance

Link to Codepen: https://codepen.io/codingkiwi_/pen/XWMBRpW

Let's consider a scenario where you have a class:

class MyClass {
  constructor(){
    this.entries = ["a"];

    //=== example change triggered from INSIDE the class ===
    setTimeout(() => {
      this.entries.push("c");
    }, 1000);
  }
}

Now, in a component, you instantiate and get an instance of that class:

const { reactive } = Vue;

const App = {
  setup() {
    const myobject = reactive(new MyClass());

    //=== example change triggered from OUTSIDE the class ===
    setTimeout(() => {
      myobject.entries.push("b");
    }, 500);
    
    return {
      myobject
    };
  }
}

The displayed entries in the DOM for the myobject.entries array will be "a" and "b", but not including "c"

Answer №1

Explained in another response, the use of reactive involves creating a proxy object to facilitate reactivity. When referencing this within a constructor, it points to the original instance of MyClass, not the proxy, rendering it non-reactive.

This points out an issue in the code where reactive considers only synchronous operations within the MyClass constructor. Engaging in asynchronous side effects within a constructor is considered bad practice due to potential complexities with consuming such constructors.

A solution could involve:

class MyClass {
  constructor(){
    // Synchronous operations only
    this.entries = ["a"];
  }

  init() {
    // Asynchronous operations, likely returning a promise
    setTimeout(() => {
      this.entries.push("c");
    }, 1000);
  }
}

Additionally,

const myobject = reactive(new MyClass());
myobject.init() // `this` is now a proxy within `init`

Answer №2

When accessing the myobject.entries array in the DOM, it will only display the entries "a" and "b", excluding "c"

This occurs because "a" was already present in the array when we made the instance reactive, and the addition of "b" occurred from outside the object through the Proxy.

To clarify: the variable const myobject does not directly hold the MyClass instance; rather, it holds a Proxy of the instance that encapsulates the original instance! This proxy is what gets passed to the DOM / Template.

The inclusion of "c" into the array happened internally within the object, not through the proxy. As a result, although "c" gets pushed to the array, it doesn't trigger any reactivity changes.

Solution:

To address this issue, explicitly mark the array that undergoes internal changes within the class as reactive, like so:

class MyClass {
  constructor(){
    this.entries = reactive(["a"]);

    //=== Example change triggered from INSIDE the class ===
    setTimeout(() => {
      this.entries.push("c");
    }, 1000);
  }
}

Alternatively, consider following the recommended approach of solely interacting with the proxied object as outlined in the documentation:

It's advisable to refrain from holding a reference to the original raw object and exclusively work with the reactive version:

Documentation: https://v3.vuejs.org/guide/reactivity.html#proxy-vs-original-identity

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

Can you explain the distinction between JSON syntax and object assignment in programming?

While exploring the Twitter Client example on Knockoutjs, one may notice that some properties are included in the JSON object while others are assigned outside of it. What distinguishes these two approaches? And why can't methods such as findSavedList ...

Having trouble removing a cookie in express?

Seems pretty straightforward. In the /user/login route, I set a cookie as shown below: if (rememberMe) { console.log('Login will be remembered.'); res.cookie('user', userObj, { signed: true, httpOnly: true, path: '/' ...

Using AJAX to remove data from a database

My PHP code snippet is displayed below: AjaxServer.php include '../include/connection.php'; // Check for the prediction if(isset($_POST["delete_me"]) && $_POST["delete_me"]=="true"){ $id = $_POST["id"]; $table = $_POST["table"]; ...

Using Selenium to determine the quantity of elements that have a similar class present

Here is the test code I am using: it('count elements by class', async t => { let count = await driver.findElements(By.css('my-questions-class')).then(v => v.length); assert.equal(count, 3); // The count should b ...

The Truffle test encounters an issue: "Error: Trying to execute a transaction that calls a contract function, but the recipient address ___ is not a contract address."

Every time I run truffle test in the terminal, I encounter the following error message: Error: Attempting to run a transaction which calls a contract function, but the recipient address 0x3ad2c00512808bd7fafa6dce844a583621f3df87 is not a contract address. ...

Guide to creating a ReactJS higher-order component using modern ES6 syntax

I´m attempting to create a ReactJS higher-order component using ES6 syntax. This is what I have so far: export const withContext = Component => class AppContextComponent extends React.Component { render() { return ( ...

Encountering an issue while trying to utilize Vuex in Vue with TypeScript

I recently utilized npm to install both vue (2.4.2) and vuex (2.3.1). However, when attempting to compile the following code snippet, I encountered the following error: https://i.stack.imgur.com/0ZKgE.png Store.ts import Vue from 'vue'; import ...

Ensure Vue line chart stays current with data passed in as props

Vue 2.x chart-js: 2.x vue-chartjs: 3.x I am currently working on a project where I need to send data from a websocket in my parent component to a child component to create a dynamic line chart that updates in real-time. In my Parent.vue file: <templ ...

What is the reason border property does not transition effectively?

I am trying to remove the border property after a certain period of time (1 second) and make it smooth. Here is what I have attempted: var elem = $('div').css({'border-top':'6px solid #FC9A24', 'border-le ...

Programming with a combination of Javascript, Angular, and Prototype to efficiently manage and

I am in a bit of a quandary, as I wish to create a function that will clear all the properties of an object and make it available to all instances of that object. To achieve this, I have added a prototype function called clear(). Here is the code snippet: ...

Generate an array containing all N-digit numbers with a sum of digits equal to S

I encountered a problem with my code translation process. Despite finding solutions in other languages, when I converted them to javascript, the expected array was not created. const find_digits = (n, sum, out, index) => { if (index > n || sum & ...

When attempting to add or store data in MongoDB, it triggers a 500 server error

Greetings, I am currently working on developing a CRUD app using the MEAN stack. The Express application loads successfully and retrieves the "contactlist" collection from the database. However, when attempting to make a POST request to "/api/contacts", an ...

Switch out the specific content within the p tag

Looking to update the highlighted text within a p tag. The code below addresses handling new line characters, but for some reason the replacement is not working as expected. Check out the HTML snippet: <p id="1-pagedata"> (d) 3 sdsdsd random: Subj ...

Tips for showcasing HTML code retrieved from a fetch request in a Vue component

Trying to integrate HTML code received from an API into my VueJS code. The API provides the following: <p>blah blah blah</p> <ul> <li> 1 </li> <li> 2 </li> </ul> Saving this code snippet into a variable, but ...

What are the differences between a Chrome app and extension? Is there any other way to access the tabs currently open in your

I need to develop an app that can access the tabs a user has open, but I'm struggling to find a way to do so without having my app run in Chrome itself. Creating an extension restricts the UI significantly, which is problematic since my app requires a ...

Using Jquery UI dialog to ensure validation

function DisplayDialog() { $("#dialogid").dialog({ width: 300, modal: true, show: 'drop', hide: 'drop', buttons: { "Ok": function () { return true; $(this).dialog('close'); }, "Cancel": func ...

Is it possible to implement AngularJS Routing for displaying HTML pages within a slideshow?

I have a vision for my website in mind - a stunning slideshow with a sleek navigation bar at the top. The idea is to have each slide represent a different category or concept, all uniquely customized with their own HTML page. However, I'm facing a cha ...

After placing two divs within another div and applying justify content, an unexpected blank space has appeared

I am currently working on a website project using the Next.js framework for React and Tailwind CSS for styling. However, I have come across an issue that is causing some trouble. My goal is to position an image on the right side of the page while keeping t ...

Utilize Angular 8 to dynamically populate Input values with data pulled from an API

I need help with setting the input value dynamically using data from my API. Once I click send, I want it to be saved in the database. However, I am struggling to dynamically populate the input field. Can someone guide me on the right approach to achieve t ...

ASP.Net does not support the compilation of AngularJS

Good Evening! I've been struggling with implementing an ASP.NET API, as my angular code seems to be not compiling correctly. I recently set up a new empty web project, installed angular and jquery through NUGET, and now I'm facing issues while ...