From: Eduardo San Martin Morote Date: Wed, 7 Apr 2021 14:31:56 +0000 (+0200) Subject: refactor: cache store create per instance X-Git-Tag: v2.0.0-alpha.11~21 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=53b428370cf00261dfe4c0e6a64576bb0da7a438;p=thirdparty%2Fvuejs%2Fpinia.git refactor: cache store create per instance --- diff --git a/src/mapHelpers.ts b/src/mapHelpers.ts index b8ae0a97..42f2b883 100644 --- a/src/mapHelpers.ts +++ b/src/mapHelpers.ts @@ -1,4 +1,6 @@ +import type Vue from 'vue' import { + GenericStore, GenericStoreDefinition, Method, StateTree, @@ -21,8 +23,21 @@ type Spread = A extends [infer L, ...infer R] ? StoreObject & Spread : unknown +function getCachedStore< + Id extends string = string, + S extends StateTree = StateTree, + G = Record, + A = Record +>(vm: Vue, useStore: StoreDefinition): Store { + const cache = vm._pStores || (vm._pStores = {}) + const id = useStore.$id + return (cache[id] || (cache[id] = useStore(vm.$pinia))) as Store +} + /** - * Allows using stores without the composition API (`setup()`) by generating an object to be spread in the `computed` field of a component. + * Allows using stores without the composition API (`setup()`) by generating an + * object to be spread in the `computed` field of a component. it accepts a list + * of store definitions. * * @example * ```js @@ -31,7 +46,7 @@ type Spread = A extends [infer L, ...infer R] * // other computed properties * ...mapStores(useUserStore, useCartStore) * }, - + * * created() { * this.userStore // store with id "user" * this.cartStore // store with id "cart" @@ -41,13 +56,13 @@ type Spread = A extends [infer L, ...infer R] * * @param stores - list of stores to map to an object */ -export function mapStores( +export function mapStores( ...stores: [...Stores] ): Spread { return stores.reduce((reduced, useStore) => { // @ts-ignore: $id is added by defineStore - reduced[useStore.$id + 'Store'] = function () { - return (useStore as GenericStoreDefinition)((this as any).$pinia) + reduced[useStore.$id + 'Store'] = function (this: Vue) { + return getCachedStore(this, useStore) } return reduced }, {} as Spread) @@ -91,15 +106,15 @@ export function mapState< ): MapStateReturn | MapStateObjectReturn { return Array.isArray(keysOrMapper) ? keysOrMapper.reduce((reduced, key) => { - // @ts-ignore: too complicated for TS - reduced[key] = function () { - return useStore((this as any).$pinia)[key] + // @ts-ignore: sorry TS + reduced[key] = function (this: Vue) { + return getCachedStore(this, useStore)[key] } return reduced }, {} as MapStateReturn) : Object.keys(keysOrMapper).reduce((reduced, key: keyof KeyMapper) => { - reduced[key] = function () { - return useStore((this as any).$pinia)[keysOrMapper[key]] + reduced[key] = function (this: Vue) { + return getCachedStore(this, useStore)[keysOrMapper[key]] } return reduced }, {} as MapStateObjectReturn) diff --git a/src/rootStore.ts b/src/rootStore.ts index 492d755d..eabd2b96 100644 --- a/src/rootStore.ts +++ b/src/rootStore.ts @@ -5,6 +5,7 @@ import { StoreWithState, StateDescriptor, PiniaCustomProperties, + GenericStore, } from './types' /** @@ -94,6 +95,12 @@ declare module '@vue/runtime-core' { * Access to the application's Pinia */ $pinia: Pinia + + /** + * Cache of stores instantiated by the current instance. Used by map + * helpers. + */ + _pStores?: Record } } @@ -134,7 +141,7 @@ export function createPinia(): Pinia { use(plugin) { /* istanbul ignore next */ - if (__DEV__) { + if (__DEV__ && !__TEST__) { console.warn( `[🍍]: The plugin API has plans to change to bring better extensibility. "pinia.use()" signature will change in the next release. It is recommended to avoid using this API.` ) diff --git a/src/types.ts b/src/types.ts index 1df5055a..14149df5 100644 --- a/src/types.ts +++ b/src/types.ts @@ -136,7 +136,6 @@ export type StoreWithGetters = { // : never // } -// has the actions without the context (this) for typings /** * Store type to build a store */ @@ -144,6 +143,7 @@ export type Store< Id extends string, S extends StateTree, G, + // has the actions without the context (this) for typings A > = StoreWithState & S & @@ -165,7 +165,7 @@ export interface StoreDefinition< } /** - * Generic version of Store + * Generic version of Store. */ export type GenericStore = Store< string, @@ -175,17 +175,14 @@ export type GenericStore = Store< > /** - * Generic version of `StoreDefinition` + * Generic version of `StoreDefinition`. */ -export interface GenericStoreDefinition { - (pinia?: Pinia | null | undefined): Store< - string, - StateTree, - Record, - Record - > - $id: string -} +export type GenericStoreDefinition = StoreDefinition< + string, + StateTree, + Record, + Record +> /** * Properties that are added to every store by `pinia.use()`