Vue3 prop updates title attribute but not computed prop

104
February 11, 2022, at 10:50 AM

I'm using an external library rendered using Vue3. It has the following component from a third part library [Edit: I realize the GitHub repo for that library is out of date, so updating with the actual code in my node_modules.]

<template>
  <div class="socket" :class="className" :title="socket.name"></div>
</template>
<script>
import { defineComponent, computed } from "vue";
import { kebab } from "./utils";
export default defineComponent({
  props: ["type", "socket"],
  setup(props) {
    const className = computed(() => {
      return kebab([props.type, props.socket.name]);
    });
    return {
      className
    };
  }
});
</script>

It renders based on a Socket object passed as a prop. When I updated the name property of the Socket, I see the title updated accordingly. However, the CSS/class does not update. I've tried $forceRefresh() on its parent, but this changes nothing.

Update: I was able to move the rendering code to my own repo, so I can now edit this component if needed.

Based on this updated code, it seems the issue is that the class is computed. Is there any way to force this to refresh?

The only time it does is when I reload the code (without refreshing the page) during vue-cli-service serve.

For reference, the | kebab filter is defined here:

Vue.filter('kebab', (str) => {
    const replace = s =>  s.toLowerCase().replace(/ /g, '-');
    return Array.isArray(str) ?  str.map(replace) : replace(str);
});

Do filtered attributes update differently? I wouldn't think so.

I was also wondering if it could be a reactivity issue, and whether I needed to set the value using Vue.set, but as I understand it that's not necessary in Vue3, and it's also not consistent with the title properly updating.

Answer 1

Computed properties are reactive, however Vue does not expect you to mutate a prop object.

From the documentation:

Warning

Note that objects and arrays in JavaScript are passed by reference, so if the prop is an array or object, mutating the object or array itself inside the child component will affect the parent state and Vue is unable to warn you against this. As a general rule, you should avoid mutating any prop, including objects and arrays as doing so ignores one-way data binding and may cause undesired results.

https://v3.vuejs.org/guide/component-props.html#one-way-data-flow

I know that this says, that you should not mutate it in the child, but the general rule is, that you should not mutate properties at all, but instead create new object with the modified data.

In your case the computed function will look for changes in the properties itself, but not the members of the properties, that is why it is not updating.

Rent Charter Buses Company
READ ALSO
Wordpress full page with animated borders effect

Wordpress full page with animated borders effect

Anybody knows a way to archive the following effect? I want to have a page with layout like picture 1jpg (and with a menu in top) full page with borders in different colors, moving, and on mouseover/hoover the border changes, like in picture 2

92
How to make noWrap work with Breadcrumbs?

How to make noWrap work with Breadcrumbs?

I'm trying to make the MUI component Breadcrumbs responsive:

106
How can I set multiple CSS styles in JavaScript?

How can I set multiple CSS styles in JavaScript?

I have the following JavaScript variables:

144
duplicate error in typescript material ui style

duplicate error in typescript material ui style

textBoxContainer: { display: '-webkit-box', display: '-webkit-flex', display: '-ms-flexbox', display: 'flex', flexWrap: 'wrap', WebkitFlexWrap: 'wrap', webkitBoxOrient: 'vertical', borderRadius: 8, },

126