Home > Back-end >  How to make a class getter reactive in Vue.js 3 with Composition API?
How to make a class getter reactive in Vue.js 3 with Composition API?

Time:07-30

I'm trying to make a class instance property reactive to display the error message if authentication fails.

userModel.ts

export class User {
  private error: string;

  set errorMessage(errorMessage: string) {
    this.error = errorMessage;
  }
  get errorMessage() {
    return this.error
  }

// other stuff...
}

LoginView.vue

import { User } from "./models/userModel";
import { ref } from 'vue';

const user = new User();
const errorMessage = ref(user.errorMessage); // <--- This is not working.
const errorMessage = ref(user.error); // <--- Neither this even if user.error property is public.

No warnings or exceptions, reactive value just remains empty. What I am missing?

CodePudding user response:

Here, you are creating new reactive variables, with the initial value being the one in your class. Your class and your ref are unrelated.

If you want your class to have reactive properties, you have to instanciate them this way:

export class User {
  private error: Ref<string> = ref('');

  public errorMessage: Computed<string> = computed({
    get() {
      return this.error.value
    },
    set(errorMessage: string) {
      this.error.value = errorMessage;
    },
  })
}

Side note: I'd recommend to use the "composables" approach instead of using classes, because class instances are not compatible with SSR.

export function useUser () {
  const user: User = reactive({})
  // other stuff...

  const error: Ref<string> = ref('');

  const errorMessage: ComputedRef<string> = computed({
    get() {
      return this.error.value
    },
    set(errorMessage: string) {
      this.error.value = errorMessage;
    },
  })

  return { user, errorMessage }
}

CodePudding user response:

Accessing a primitive property by value like ref(user.error) can't be reactive, no matter it's a getter or not, in this case it doesn't differ from ref(undefined).

For own enumerable property it could be:

let user = reactive(new User());
let { error } = toRefs(user);

It won't handle property accessors, they need to be explicitly accessed with computed property:

let errorMessage = computed({
  get: () => user.errorMessage,
  set: value => { user.errorMessage = value }
});

Whether it's a getter or regular property doesn't affect how a computed works because an accessor is defined on class prototype and accesses reactive this.error (this can be a problem when non-reactive this is bound in a constructor, like is shown here and here).

  • Related