Pinia: $reset alternative when using setup syntax
Asked Answered
K

2

11

I have a pinia store created with setup syntax like:

defineStore('id', () => {
  const counter = ref(0)
  
  return { counter }
})

Everything has been working great with setup syntax because I can re-use other pinia stores.

Now, however, I see the need to re-use Pinia stores on other pages but their state needs to be reset.

In Vuex for example, I was using registerModule and unregisterModule to achieve having a fresh store.

So the question is: How to reset the pinia store with setup syntax?

Note: The $reset() method is only implemented for stores defined with the object syntax, so that is not an option.

Note 2: I know that I can do it manually by creating a function where you set all the state values to their initial ones

Note 3: I found $dispose but it doesn't work. If $dispose is the answer, then how it works resetting the store between 2 components?

Koosis answered 31/3, 2022 at 10:24 Comment(2)
Reset feature is supported by this library github.com/huybuidac/vuex-extensions. Just $store.reset()Pragmaticism
@HuyBuiDac That library is for Vuex, but this question is about Pinia.Montevideo
M
12

You can use a Pinia plugin that adds a $reset() function to all stores:

  1. On the Pinia instance, call use() with a function that receives a store property. This function is a Pinia plugin.

  2. Deep-copy store.$state as the initial state. A utility like lodash.clonedeep is recommended for state that includes nested properties or complex data types, such as Set.

  3. Define store.$reset() as a function that calls store.$patch() with a deep-clone of the initial state from above.

  4. We use Object.assign to make it work properly with objects see here. Same way pinia does itself when defining $reset for Options API.

// store.js
import { createPinia } from 'pinia'
import cloneDeep from 'lodash.clonedeep'

const store = createPinia()
1️⃣
store.use(({ store }) => {
  2️⃣
  const initialState = cloneDeep(store.$state)
  3️⃣
  store.$reset = () => {
    store.$patch($state => {
      4️⃣
      Object.assign($state, initialState)
    })
  }
})

demo


Feel free to read the article based on this answer: How to reset stores created with function/setup syntax

Montevideo answered 6/4, 2022 at 1:15 Comment(7)
store.$state is an empty object if you use setup syntax? I am not sure why this is the accepted answer. Is it outdated?Susysuter
@Susysuter Not sure what you mean. The solution works as seen in the linked StackBlitz (although it's possible that code is outdated, as I've not kept up with any recent releases of those libs). If you still need help, I recommend posting a new question with details to reproduce the problem so that someone familiar with the topic can help you. I'll chime in if I can.Montevideo
This approach works, however for me it breaks options-api defined stores (I have a mix while we transition to setup func). Is there a reliable method to establish if the store is defined via options-api syntax and skip overwriting the $reset method? Checking if store.$reset isn't sufficient, as it's defined on both syntax stores.Vistula
@Vistula To clarify, at the time of the original writing, $reset was not a built-in function of the store, and this answer provided a way to define it.Montevideo
I realize I did not point out that $reset is still not supported with setup syntax, however the property exists, perhaps as a stub only so it logs a "$reset is not supported" message. This makes the store syntax/type difficult to differentiate in an app which combines both setup syntax store and options-api syntax storesVistula
I found a problem with this. It throws an error when we return a ref as readonlyKoosis
I ended up, instead of prop: readonly(myProp) I used prop: computed(() => myProp.value)Koosis
P
2

You can do this as suggested in the documentation here

myStore.$dispose()

const pinia = usePinia()

delete pinia.state.value[myStore.$id]
Pournaras answered 14/12, 2022 at 14:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.