diff --git a/packages/pinia/__tests__/multipleRoots.spec.ts b/packages/pinia/__tests__/multipleRoots.spec.ts
new file mode 100644
index 0000000000..3efdcfe6ef
--- /dev/null
+++ b/packages/pinia/__tests__/multipleRoots.spec.ts
@@ -0,0 +1,98 @@
+import { createPinia, defineStore, providePinia } from '../src'
+import { mount } from '@vue/test-utils'
+import { defineComponent } from 'vue'
+
+describe('Multiple Roots', () => {
+ function defineMyStore() {
+ return defineStore({
+ id: 'main',
+ state: () => ({
+ n: 0,
+ }),
+ })
+ }
+
+ it('uses the same root in child components by default', () => {
+ expect.assertions(2)
+ const pinia = createPinia()
+ const useStore = defineMyStore()
+
+ const ChildComponent = defineComponent({
+ template: 'no',
+ setup() {
+ const store = useStore()
+ expect(store.n).toBe(1)
+ },
+ })
+
+ mount(
+ {
+ template: '',
+ components: { ChildComponent },
+ setup() {
+ const store = useStore()
+ expect(store.n).toBe(0)
+ store.n++
+ },
+ },
+ { global: { plugins: [pinia] } }
+ )
+ })
+
+ it('can use a new pinia root for all child components', async () => {
+ expect.assertions(2)
+ const pinia = createPinia()
+ const useStore = defineMyStore()
+
+ const ChildComponent = defineComponent({
+ template: 'no',
+ setup() {
+ const store = useStore()
+ expect(store.n).toBe(0)
+ },
+ })
+ mount(
+ {
+ template: '',
+ components: { ChildComponent },
+ setup() {
+ providePinia(createPinia())
+ const store = useStore()
+ expect(store.n).toBe(0)
+ store.n++
+ },
+ },
+ { global: { plugins: [pinia] } }
+ )
+ })
+
+ it('state is shared between child components', async () => {
+ expect.assertions(3)
+ const pinia = createPinia()
+ const useStore = defineMyStore()
+
+ const ChildComponent = defineComponent({
+ template: 'no',
+ props: { counter: { type: Number, required: true } },
+ setup(props: { counter: number }) {
+ const store = useStore()
+ expect(store.n).toBe(props.counter)
+ store.n++
+ },
+ })
+ mount(
+ {
+ template:
+ '',
+ components: { ChildComponent },
+ setup() {
+ const store = useStore()
+ expect(store.n).toBe(0)
+ store.n++
+ providePinia(createPinia())
+ },
+ },
+ { global: { plugins: [pinia] } }
+ )
+ })
+})
diff --git a/packages/pinia/src/index.ts b/packages/pinia/src/index.ts
index 99fbd400e9..6764c85258 100644
--- a/packages/pinia/src/index.ts
+++ b/packages/pinia/src/index.ts
@@ -1,7 +1,7 @@
/**
* @module pinia
*/
-export { setActivePinia, getActivePinia } from './rootStore'
+export { setActivePinia, getActivePinia, providePinia } from './rootStore'
export { createPinia } from './createPinia'
export type {
Pinia,
diff --git a/packages/pinia/src/rootStore.ts b/packages/pinia/src/rootStore.ts
index 833566dd18..4bdf81777f 100644
--- a/packages/pinia/src/rootStore.ts
+++ b/packages/pinia/src/rootStore.ts
@@ -4,6 +4,7 @@ import {
getCurrentInstance,
inject,
InjectionKey,
+ provide,
Ref,
} from 'vue-demi'
import {
@@ -97,6 +98,13 @@ export const piniaSymbol = (
__DEV__ ? Symbol('pinia') : /* istanbul ignore next */ Symbol()
) as InjectionKey
+/**
+ * Define which pinia to use in all child components.
+ */
+export function providePinia(pinia: Pinia) {
+ provide(piniaSymbol, pinia)
+}
+
/**
* Context argument passed to Pinia plugins.
*/