Pinia + Vue 3 state reactivity - alternative to storeToRefs

700 views Asked by At

I have the following composable useLocations.js:

export const useLocations = defineStore('useLocations', () => {
    const state = reactive({
        data: 1
    })

    const update = () => {
        state.data = 2
    }

    return {
        ...toRefs(state),
        update
    }
})

and I am accesing it in my locations.vue component like this:

const { data, update } = useLocations
update()
console.log(data) // 1

I am expecting console.log(data) to be 2 not 1

I have tried to access the store like this, and this indeed works:

const store = useLocations()
const { data } = storeToRefs(store)
const { update } = store
update()
console.log(data) // 2

but I would like a solution without storeToRefs, and I don't understand why toRefs in the composable doesn't work.

According to Vue documentation https://vuejs.org/api/reactivity-utilities.html#torefs this is my exact scenario, and the reactivity breaks somehow.

LE: I would like a solution without storeToRefs so I can avoid calling the store twice in my component, once for state and once for the actions.

1

There are 1 answers

1
Estus Flask On BEST ANSWER

toRefs doesn't serve a good purpose inside store setup function because it unwraps all the refs that are returned. Notice that console.log(data) outputs "1" and not a ref. It's works the same way as the refs inside reactive, as Pinia uses Vue reactivity internally.

It's unnecessary to destructure a store, it can be used as store.data and store.update. Otherwise storeToRefs is supposed to be used as in the question, this produces no overhead.

In case you need to modify this behaviour for some reason, custom helper can be created that will add additional keys to storeToRefs object based on certain criteria, e.g. for actions:

const storeToRefsWithActions = store => ({
  ...storeToRefs(store),
  ...Object.fromEntries(
    Object.entries(store)
    .filter(
      ([key, val]) => !key.startsWith('$') && typeof val === 'function'
    )
  )
})