Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vue 3: Why is my composable not reactive?

I want to use 1 composable from within another. My first composable is basically a super lightweight version of Vuex:

import {
  reactive,
  readonly,
} from 'vue';

const state = reactive({
  settings: {
    loading: true,
  },
  cart: {
    loading: true,
    items: [],
  },
});

export default {
  state: readonly(state),
};

When I try to use this in another composable, the cart is not being reactive.

In my other composable I have:

import store from '@/store';
watch(store.state.cart, () => {
  console.log('test');
});

And it doesn't seem to react to anything. When I try calling .value on it, its undefined, as if it's not a proxy.

I also tried using inject('store') and that seems to do the same thing.

I want to watch when any part of the cart changes.

like image 612
Tallboy Avatar asked Jan 19 '26 22:01

Tallboy


1 Answers

The answer is long and involved, but it basically boils down to:

  1. Part of it is a javascript problem, in that the way I was updating cart was by replacing the entire key of the object with an API call, so the inner cart key was getting updated with a different reference. You can visualize the problem here

  2. I had to use toRef which is subtly different from ref, in that it is specifically for extracting reactive keys out of a reactive object. I thought this only applied to destructuring but it also applies to simply saying const cart = store.state.cart, as when I updated the cart this cart variable would point to the old reference. toRef solves this by writing: const cart = toRef(store.state, 'cart')

like image 179
Tallboy Avatar answered Jan 22 '26 19:01

Tallboy



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!