11# Vue Cache Store
22Dynamically create, re-use, and destroy [ Pinia] ( https://pinia.vuejs.org/ ) like stores.
33
4- ## Use Case
5- When you need reusable non-trivial computed/reactive objects in multiple components.
6-
74## Installation
85
96` $ npm i vue-cache-store `
107
8+ ## Primary Use Case
9+ When using non-trivial derived reactive objects in multiple components.
10+
11+ ``` ts
12+ // person-data.ts
13+ type Person = {
14+ id: number ,
15+ name: string ,
16+ }
17+
18+ export const people = ref <Person []>([{
19+ id: 99 ,
20+ firstName: ' Jim' ,
21+ lastName: ' Kirk'
22+ }])
23+ export const getPerson = (id : number ) => people .value .find (person => person .id === id )
24+
25+ export const getPersonInfo = (person : Person ) => {
26+ const firstName = computed (() => person .firstName )
27+ const lastName = computed (() => person .lastName )
28+ // 🧠 imagine this is non-trivial and complicated 🧠
29+ return {
30+ id: computed (() => id ),
31+ firstName ,
32+ lastName ,
33+ fullName: computed (() => firstName .value + ' ' + lastName .value )
34+ }
35+ }
36+
37+ // in multiple components
38+ const person = getPerson (99 )
39+ const info = getPersonInfo (person )
40+ // each time getPersonInfo() is called
41+ // it is re-run and creates redundant copies of its info object
42+ ```
43+
44+ ### Solution
45+ Reusable non-trivial computed/reactive objects in multiple components.
46+
47+ ``` ts
48+ // person-info.ts
49+ import { computed } from ' vue'
50+ import { watchRecordStore } from ' vue-cache-store'
51+ import { getPerson , getPersonInfo } from ' person-data.ts'
52+
53+ export const personInfo = watchRecordStore (
54+ // record watcher
55+ // auto clears cached object if returns falsy
56+ (id : number ) => getPerson (id ),
57+ // cached object creator
58+ (person : Person ) => getPersonInfo (person ),
59+ )
60+ ```
61+ ``` ts
62+ // inside multiple components
63+ import { personInfo } from ' person-info.ts'
64+
65+ // returns reactive object
66+ const reactivePerson = personInfo .get (id )
67+ // ❌ dereferencing reactive objects breaks them
68+ const { lastName } = personInfo .get (id )
69+ // ✅ use the getRefs() instead
70+ const { firstName, fullName } = personInfo .getRefs (id )
71+
72+ const computedLastName = computed (() => personInfo .get (id ).lastName )
73+ ```
74+
1175## Usage
1276
1377### Define a Cache Store
1478Cache stores are designed to behave similar to [ Pinia] ( https://pinia.vuejs.org/ ) stores.
15- The value returned by ` usePersonCache() ` can be used similar to Pinia.
79+ The value returned by ` usePersonCache().get(id) ` can be used similar to a Pinia store .
1680``` ts
1781// person-cache.ts
1882import { defineCacheStore } from ' vue-cache-store'
1983import { computed } from ' vue'
20- // example service
21- import { getRecordInfo } from ' record-info-getter'
84+
85+ // simplified data source
86+ const people = ref ([{
87+ id: 99 ,
88+ firstName: ' Jim' ,
89+ lastName: ' Kirk'
90+ }])
91+
92+ const getPerson = (id : number ) => people .value .find (person => person .id === id )
2293
2394export const usePersonCache = defineCacheStore ((id ) => {
24- const info = getRecordInfo (id )
25- const firstName = computed (() => info .firstName )
26- const lastName = computed (() => info .lastName )
95+ const person = getPerson (id )
96+ const firstName = computed (() => person .firstName )
97+ const lastName = computed (() => person .lastName )
2798
2899 return {
29100 id: computed (() => id ),
@@ -102,12 +173,14 @@ type CacheStore = {
102173 clear(): void ,
103174 // increase use count by 1
104175 mount(): void ,
105- // decrease use count by 1
106- // and clear if count is 0
107- // and autoClearUnused option is true
176+ // decrease use count by 1
177+ // if autoClearUnused option is true,
178+ // calls clear(), clearing the whole store if count becomes 0
108179 unMount(): void ,
109180}
110181const cache: CacheStore = usePersonCache ()
182+
183+ const personInfo = cache .get (99 )
111184```
112185
113186### Cache Store Context
@@ -141,39 +214,38 @@ Designed to cache an object store based on a record object.
141214
142215#### ` defineRecordStore() `
143216Internally calls and returns ` defineCacheStore() `
217+
144218``` ts
145219// person-info.ts
146220import { computed , ref } from ' vue'
147221import { defineRecordStore } from ' vue-cache-store'
148222
149223// minimal example
150- type Person = {
151- id: number ,
152- name: string ,
153- }
154-
155- const people = ref <Person []>([{
224+ const people = ref ([{
156225 id: 99 ,
157- name: ' Jim'
226+ name: ' Jim' ,
158227}])
159228
160- const getPerson = (id : number ) => people .value .find (person => person .id === id )
161- const removePerson = (id : number ) => {
229+ const getPerson = (id ) => people .value .find (person => person .id === id )
230+ const removePerson = (id ) => {
162231 const index = people .value .findIndex (person => person .id === id )
163232 if (index > - 1 ) {
164233 people .value .splice (index , 1 )
165234 }
166235}
167236// defineRecordStore() internally calls and returns defineCacheStore()
168- const usePersonInfo = defineRecordStore ({
169- getRecord(id : number ) {
170- // return value is watched
237+ export const usePersonInfo = defineRecordStore (
238+ // record watcher
239+ (id : number ) => {
240+ // this function is watched
171241 // if the return value becomes falsy
172242 // the cached object is removed automatically
173243 return getPerson (id )
174244 },
175- create(record : Person ) {
176- // return value of this function is cached
245+
246+ // cached object creator
247+ (record : Person ) => {
248+ // return value of this function is cached.
177249 // even if used by multiple components
178250 // it will not be called repeatedly
179251 const { id : personId, name } = toRefs (record )
@@ -184,7 +256,7 @@ const usePersonInfo = defineRecordStore({
184256 nameLength: computed (() => record .name .length || 0 ),
185257 }
186258 },
187- } )
259+ )
188260
189261const personInfo = usePersonInfo ()
190262
@@ -214,37 +286,32 @@ personInfo.has(99) // false
214286personInfo .ids () // []
215287```
216288
217- #### ` makeRecordStore ()`
289+ #### ` watchRecordStore ()`
218290``` ts
219- import { makeRecordStore } from ' vue-cache-store'
291+ import { watchRecordStore } from ' vue-cache-store'
220292
221- const personInfo = makeRecordStore ({
222- getRecord(id ) {
223- // ...
224- },
225- create(record ) {
226- // ...
227- },
228- })
229- // proxy for
230- const personInfoAlso = defineRecordStore (/* ... */ )()
231- // with more type clarity
293+ export const personInfo = watchRecordStore (/* ... */ )
294+
295+ // watchRecordStore() internally does the following:
296+ const useInfo = defineRecordStore (/* ... */ )()
297+ // with typing intact
298+ return useInfo ()
232299```
233300
234- #### ` makeRecordStore() ` Usage with a [ Pinia] ( https://pinia.vuejs.org/ ) store
301+ #### Usage within a [ Pinia] ( https://pinia.vuejs.org/ ) store
235302
236303``` ts
237304// person-store.ts
238305import { defineStore } from ' pinia'
239- import { makeRecordStore } from ' vue-cache-store'
306+ import { watchRecordStore } from ' vue-cache-store'
240307
241308// minimal example
242309type Person = {
243310 id: number ,
244311 name: string ,
245312}
246313
247- const usePersonStore = defineStore (' people' , () => {
314+ export const usePersonStore = defineStore (' people' , () => {
248315 const people = ref <Person []>([{
249316 id: 99 ,
250317 name: ' Jim' ,
@@ -272,21 +339,19 @@ const usePersonStore = defineStore('people', () => {
272339 item .name = name
273340 }
274341
275- const personInfo = makeRecordStore ({
276- getRecord(id : number ) {
277- return getPerson (id )
278- },
279- create(record : Person ) {
342+ const personInfo = watchRecordStore (
343+ (id : number ) => getPerson (id ),
344+ (record : Person ) => {
280345 const person = computed (() => record )
281- const { name } = toRefs (record )
346+ const { id : personId, name } = toRefs (record )
282347
283348 return {
284- id: computed (() => person . value . id ) ,
349+ id: personId ,
285350 name ,
286351 nameLength: computed (() => person .value ?.name .length || 0 ),
287352 }
288- },
289- } )
353+ }
354+ )
290355
291356 return {
292357 people ,
@@ -334,10 +399,10 @@ personStore.personInfo.ids() // []
334399
335400When defining a cache store the second argument is a default options object.
336401
337- | option | description |
338- | :----------------------| :-------------------------------------------------------------------------------------------------|
339- | ` autoMountAndUnMount ` | If true, automatically tracks the number of mounted components using the cache store |
340- | ` autoClearUnused ` | If true, when there are no longer any mounted components using a cache store it will be cleared. |
402+ | option | description |
403+ | :----------------------| :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
404+ | ` autoMountAndUnMount ` | If true, automatically tracks the number of mounted components using the cache store. < br > Mounting is tracked when calling in the root of a component. Example: ` const personInfo = usePersonInfo() ` |
405+ | ` autoClearUnused ` | If true, when there are no longer any mounted components using a cache store it will be cleared. |
341406
342407#### ` defineCacheStore() ` Options
343408``` ts
@@ -387,6 +452,7 @@ const options = {
387452}
388453```
389454#### ` defineRecordStore() ` Options Usage
455+
390456``` ts
391457// person-record.ts
392458import { defineRecordStore } from ' vue-cache-store'
@@ -398,18 +464,18 @@ defineRecordStore.setGlobalDefaultOptions({
398464})
399465
400466// defining a record store with store default options overriding global defaults
401- export const usePersonRecord = defineRecordStore ({
402- getRecord (id ) {
403-
467+ export const usePersonRecord = defineRecordStore (
468+ (id ) => {
469+ // ...
404470 },
405- create() {
406-
471+ () => {
472+ // ...
407473 },
408- defaultOptions: {
474+ {
409475 autoMountAndUnMount: false ,
410476 autoClearUnused: false ,
411- }
412- } )
477+ },
478+ )
413479
414480// inside a component
415481// overrides usePersonRecord default options and defineRecordStore global defaults
@@ -418,6 +484,26 @@ const personCache = usePersonRecord({
418484 autoClearUnused: false ,
419485})
420486```
487+ #### ` watchRecordStore() ` Options
488+ ` watchRecordStore() ` calls ` defineRecordStore() ` internally so it uses the global default options ` defineRecordStore() `
489+ ``` ts
490+ import { watchRecordStore } from ' vue-cache-store'
491+
492+ // defining a record store with store default options overriding global defaults
493+ export const usePersonRecord = watchRecordStore (
494+ (id ) => {
495+ // ...
496+ },
497+ () => {
498+ // ...
499+ },
500+ {
501+ autoMountAndUnMount: false ,
502+ autoClearUnused: false ,
503+ },
504+ )
505+ ```
506+
421507
422508### API
423509
0 commit comments