Skip to content

Commit ee7911b

Browse files
committed
feat: expose providePinia to use multiple root stores
1 parent eaed48a commit ee7911b

File tree

3 files changed

+107
-1
lines changed

3 files changed

+107
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import { createPinia, defineStore, providePinia } from '../src'
2+
import { mount } from '@vue/test-utils'
3+
import { defineComponent } from 'vue'
4+
5+
describe('Multiple Roots', () => {
6+
function defineMyStore() {
7+
return defineStore({
8+
id: 'main',
9+
state: () => ({
10+
n: 0,
11+
}),
12+
})
13+
}
14+
15+
it('uses the same root in child components by default', () => {
16+
expect.assertions(2)
17+
const pinia = createPinia()
18+
const useStore = defineMyStore()
19+
20+
const ChildComponent = defineComponent({
21+
template: 'no',
22+
setup() {
23+
const store = useStore()
24+
expect(store.n).toBe(1)
25+
},
26+
})
27+
28+
mount(
29+
{
30+
template: '<ChildComponent />',
31+
components: { ChildComponent },
32+
setup() {
33+
const store = useStore()
34+
expect(store.n).toBe(0)
35+
store.n++
36+
},
37+
},
38+
{ global: { plugins: [pinia] } }
39+
)
40+
})
41+
42+
it('can use a new pinia root for all child components', async () => {
43+
expect.assertions(2)
44+
const pinia = createPinia()
45+
const useStore = defineMyStore()
46+
47+
const ChildComponent = defineComponent({
48+
template: 'no',
49+
setup() {
50+
const store = useStore()
51+
expect(store.n).toBe(0)
52+
},
53+
})
54+
mount(
55+
{
56+
template: '<ChildComponent />',
57+
components: { ChildComponent },
58+
setup() {
59+
providePinia(createPinia())
60+
const store = useStore()
61+
expect(store.n).toBe(0)
62+
store.n++
63+
},
64+
},
65+
{ global: { plugins: [pinia] } }
66+
)
67+
})
68+
69+
it('state is shared between child components', async () => {
70+
expect.assertions(3)
71+
const pinia = createPinia()
72+
const useStore = defineMyStore()
73+
74+
const ChildComponent = defineComponent({
75+
template: 'no',
76+
props: { counter: { type: Number, required: true } },
77+
setup(props: { counter: number }) {
78+
const store = useStore()
79+
expect(store.n).toBe(props.counter)
80+
store.n++
81+
},
82+
})
83+
mount(
84+
{
85+
template:
86+
'<ChildComponent :counter="0" /><ChildComponent :counter="1" />',
87+
components: { ChildComponent },
88+
setup() {
89+
const store = useStore()
90+
expect(store.n).toBe(0)
91+
store.n++
92+
providePinia(createPinia())
93+
},
94+
},
95+
{ global: { plugins: [pinia] } }
96+
)
97+
})
98+
})

packages/pinia/src/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**
22
* @module pinia
33
*/
4-
export { setActivePinia, getActivePinia } from './rootStore'
4+
export { setActivePinia, getActivePinia, providePinia } from './rootStore'
55
export { createPinia } from './createPinia'
66
export type {
77
Pinia,

packages/pinia/src/rootStore.ts

+8
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
getCurrentInstance,
55
inject,
66
InjectionKey,
7+
provide,
78
Ref,
89
} from 'vue-demi'
910
import {
@@ -97,6 +98,13 @@ export const piniaSymbol = (
9798
__DEV__ ? Symbol('pinia') : /* istanbul ignore next */ Symbol()
9899
) as InjectionKey<Pinia>
99100

101+
/**
102+
* Define which pinia to use in all child components.
103+
*/
104+
export function providePinia(pinia: Pinia) {
105+
provide(piniaSymbol, pinia)
106+
}
107+
100108
/**
101109
* Context argument passed to Pinia plugins.
102110
*/

0 commit comments

Comments
 (0)