Skip to content

Commit

Permalink
fix: allow $reset to be overridden by plugins (#2054)
Browse files Browse the repository at this point in the history
Co-authored-by: Cygnut <ligand@hotmail.co.uk>
  • Loading branch information
posva and its-lee committed Mar 6, 2023
1 parent 5368a6a commit 709e2b1
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 14 deletions.
30 changes: 29 additions & 1 deletion packages/docs/core-concepts/plugins.md
Expand Up @@ -144,7 +144,7 @@ If you are using **Vue 2**, Pinia is subject to the [same reactivity caveats](ht
```js
import { set, toRef } from '@vue/composition-api'
pinia.use(({ store }) => {
if (!Object.prototype.hasOwnProperty(store.$state, 'hello')) {
if (!Object.prototype.hasOwnProperty(store.$state, 'secret')) {
const secretRef = ref('secret')
// If the data is meant to be used during SSR, you should
// set it on the `$state` property so it is serialized and
Expand All @@ -160,6 +160,34 @@ pinia.use(({ store }) => {

:::

#### Resetting state added in plugins

By default, `$reset()` will not reset state added by plugins but you can override it to also reset the state you add:

```js
import { toRef, ref } from 'vue'

pinia.use(({ store }) => {
// this is the same code as above for reference
if (!Object.prototype.hasOwnProperty(store.$state, 'hasError')) {
const hasError = ref(false)
store.$state.hasError = hasError
}
store.hasError = toRef(store.$state, 'hasError')

// make sure to set the context (`this`) to the store
const originalReset = store.$reset.bind(store)

// override the $reset function
return {
$reset() {
originalReset()
store.hasError = false
}
}
})
```

## Adding new external properties

When adding external properties, class instances that come from other libraries, or simply things that are not reactive, you should wrap the object with `markRaw()` before passing it to pinia. Here is an example adding the router to every store:
Expand Down
39 changes: 36 additions & 3 deletions packages/pinia/__tests__/storePlugins.spec.ts
Expand Up @@ -23,9 +23,7 @@ declare module '../src' {
}

describe('store plugins', () => {
const useStore = defineStore({
id: 'test',

const useStore = defineStore('test', {
actions: {
incrementN() {
return this.pluginN++
Expand Down Expand Up @@ -64,6 +62,41 @@ describe('store plugins', () => {
store.idFromPlugin == 'hello'
})

it('overrides $reset', () => {
const pinia = createPinia()

const useStore = defineStore('main', {
state: () => ({ n: 0 }),
})

mount({ template: 'none' }, { global: { plugins: [pinia] } })

pinia.use(({ app, store }) => {
if (!store.$state.hasOwnProperty('pluginN')) {
// @ts-expect-error: cannot be a ref yet
store.$state.pluginN = ref(20)
}
// @ts-expect-error: TODO: allow setting refs
store.pluginN = toRef(store.$state, 'pluginN')

const originalReset = store.$reset.bind(store)
return {
uid: app._uid,
$reset() {
originalReset()
store.pluginN = 20
},
}
})

const store = useStore(pinia)

store.pluginN = 200
store.$reset()
expect(store.$state.pluginN).toBe(20)
expect(store.pluginN).toBe(20)
})

it('can install plugins before installing pinia', () => {
const pinia = createPinia()

Expand Down
21 changes: 11 additions & 10 deletions packages/pinia/src/store.ts
Expand Up @@ -195,14 +195,6 @@ function createOptionsStore<

store = createSetupStore(id, setup, options, pinia, hot, true)

store.$reset = function $reset() {
const newState = state ? state() : {}
// we use a patch to group all changes into one single subscription
this.$patch(($state) => {
assign($state, newState)
})
}

return store as any
}

Expand Down Expand Up @@ -329,8 +321,17 @@ function createSetupStore<
)
}

/* istanbul ignore next */
const $reset = __DEV__
const $reset = isOptionsStore
? function $reset(this: _StoreWithState<Id, S, G, A>) {
const { state } = options as DefineStoreOptions<Id, S, G, A>
const newState = state ? state() : {}
// we use a patch to group all changes into one single subscription
this.$patch(($state) => {
assign($state, newState)
})
}
: /* istanbul ignore next */
__DEV__
? () => {
throw new Error(
`🍍: Store "${$id}" is built using the setup syntax and does not implement $reset().`
Expand Down

0 comments on commit 709e2b1

Please sign in to comment.