AndyJamesN
AndyJamesN

Reputation: 498

Reactive object in Vue 3 Composition API not updating with a @click event

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

Upvotes: 2

Views: 9569

Answers (4)

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' }, );

Upvotes: 0

MaxSemenov
MaxSemenov

Reputation: 9

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

Upvotes: -1

MD SHAYON
MD SHAYON

Reputation: 8063

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

Upvotes: 0

obe
obe

Reputation: 7806

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';

Upvotes: 2

Related Questions