2

I seem to be missing something with the Vue Composition API when it comes to using and updating reactive objects.

See the below code. I'm expecting the click event to update the {{colors}} output in the template when a color is added.

<template>
  <div>
    <!-- {{colors}} Is not updated in the DOM on click event -->
    <pre>{{ colors }}</pre>
    <button @click="addColor">add color</button>
  </div>
</template>

<script>
import { reactive } from 'vue';

export default {
  setup() {
    let colors = reactive({ green: '#ccc000' });

    function addColor() {
      // By cloning and creating a new merged object
      colors = Object.assign({}, colors, { red: '#fff000' });
      // Or by changing the object directly
      colors.orange = '#322332'; // Also does not work
      console.log(colors); // Logs out the correct value
    }

    return {
      colors,
      addColor,
    };
  },
};
</script>

I can see in the console log the value of colors is being updated but not in the DOM.

Here is a code sandbox of the code

https://codesandbox.io/s/mystifying-roentgen-rox9k?file=/src/App.vue

1
  • I checked sandbox link you provided. In the sandbox , the DOM is updated by click! Commented Jan 30, 2024 at 10:03

4 Answers 4

2

You probably shouldn't create a new object:

colors = Object.assign({}, colors, { red: '#fff000' });

Instead, try to manipulate the existing object:

delete colors.green;
colors.red = '#fff000';
Sign up to request clarification or add additional context in comments.

9 Comments

I actually updated my example a little earlier showing exactly what you suggested as it also does not work. edit: I removed the Object assign line and it works
Instead of the colors = Object.assign(), not in addition.
@AndyJamesN You've replaced your reactive proxy with a normal object. That's why it didn't react when you manipulated it directly.
and by the way, a cooler syntax for colors = Object.assign... would be colors = { ...colors, red: '#fff000' } :)
What I am going to do as a workaround is use Vuex store instead. This will allow me to edit my main color object (which is in reality much more complex than just colors) as needed and use computed to keep things reactive. Thanks for all the feedback.
|
0

your colors object and function should be like this

 const colors = reactive({ green: "#ccc000" });
    function addColor() {
      colors.green = "rgb(23, 117, 109)";
    }

don't forget to return colors and addColor from setup

in your template add

<pre>{{ colors.green }}</pre>
    <button @click="addColor">add color</button>

this should work

Comments

0

After this assignment:

colors = Object.assign({}, colors, { red: '#fff000' });

you set a new object without reactivity to the colors variable to change it to the correct code you can change it to this:

colors = Object.assign(colors, { red: '#fff000' }, );

Comments

-1

By doing so first:

colors = Object.assign({}, colors, { red: '#fff000' });

You damage the reactivity

Now this absolutely appropriate line of code colors.orange = '#322332' does not work since the reactivity already lost

The solution is - remove the first attempt

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.