0
# Options API Integration
1
2
Map helper functions that provide compatibility with Vue's Options API, allowing stores to be mapped to component computed properties and methods.
3
4
## Capabilities
5
6
### Map Stores
7
8
Maps multiple stores to component computed properties, providing access to store instances via `this`.
9
10
```typescript { .api }
11
/**
12
* Maps multiple stores to component computed properties
13
* @param stores - Array of store definitions to map
14
* @returns Object with store accessor computed properties
15
*/
16
function mapStores<Stores extends any[]>(...stores: [...Stores]): _Spread<Stores>;
17
18
type _Spread<A extends readonly any[]> = A extends readonly [infer L, ...infer R]
19
? _StoreObject<L> & _Spread<R>
20
: unknown;
21
22
type _StoreObject<S> = S extends StoreDefinition<infer Id, infer State, infer Getters, infer Actions>
23
? {
24
[K in `${Id}${MapStoresCustomization extends Record<'suffix', infer Suffix>
25
? Suffix
26
: 'Store'}`]: () => Store<Id, State, Getters, Actions>
27
}
28
: {};
29
```
30
31
**Usage Examples:**
32
33
```typescript
34
import { mapStores } from "pinia";
35
import { useUserStore } from "./stores/user";
36
import { useCartStore } from "./stores/cart";
37
import { useProductStore } from "./stores/product";
38
39
export default {
40
computed: {
41
// Maps stores to computed properties ending with "Store"
42
...mapStores(useUserStore, useCartStore, useProductStore),
43
},
44
methods: {
45
handlePurchase() {
46
// Access stores via computed properties
47
this.userStore.updateLastPurchase();
48
this.cartStore.clear();
49
this.productStore.decreaseInventory(this.cartStore.items);
50
},
51
},
52
};
53
54
// Custom suffix
55
import { setMapStoreSuffix } from "pinia";
56
setMapStoreSuffix("Repository");
57
58
export default {
59
computed: {
60
...mapStores(useUserStore), // Creates userRepository computed property
61
},
62
};
63
```
64
65
### Map State
66
67
Maps store state properties to component computed properties, providing reactive access to state values.
68
69
```typescript { .api }
70
/**
71
* Maps store state properties to component computed properties
72
* @param useStore - Store definition to map from
73
* @param keys - Array of state property keys to map
74
* @returns Object with reactive computed properties
75
*/
76
function mapState<
77
Id extends string,
78
S extends StateTree,
79
G extends _GettersTree<S>,
80
A,
81
Keys extends keyof (S & G)
82
>(
83
useStore: StoreDefinition<Id, S, G, A>,
84
keys: readonly Keys[]
85
): _MapStateReturn<S & G, Keys>;
86
87
/**
88
* Maps store state properties with custom names or functions
89
* @param useStore - Store definition to map from
90
* @param keysObject - Object mapping local names to store properties or functions
91
* @returns Object with reactive computed properties
92
*/
93
function mapState<
94
Id extends string,
95
S extends StateTree,
96
G extends _GettersTree<S>,
97
A
98
>(
99
useStore: StoreDefinition<Id, S, G, A>,
100
keysObject: Record<string, keyof (S & G) | ((store: Store<Id, S, G, A>) => any)>
101
): _MapStateObjectReturn<Id, S, G, A>;
102
103
type _MapStateReturn<T, Keys extends keyof T> = {
104
[K in Keys]: () => T[K];
105
};
106
107
type _MapStateObjectReturn<Id extends string, S extends StateTree, G, A> = Record<
108
string,
109
() => any
110
>;
111
```
112
113
**Usage Examples:**
114
115
```typescript
116
import { mapState } from "pinia";
117
import { useCounterStore } from "./stores/counter";
118
import { useUserStore } from "./stores/user";
119
120
export default {
121
computed: {
122
// Simple array mapping
123
...mapState(useCounterStore, ["count", "doubleCount"]),
124
...mapState(useUserStore, ["currentUser", "isLoggedIn"]),
125
126
// Object mapping with custom names
127
...mapState(useUserStore, {
128
user: "currentUser",
129
loggedIn: "isLoggedIn",
130
username: (store) => store.currentUser?.name || "Guest",
131
}),
132
133
// Mixed usage
134
...mapState(useCounterStore, {
135
currentCount: "count",
136
isEven: (store) => store.count % 2 === 0,
137
}),
138
},
139
template: `
140
<div>
141
<p>Count: {{ count }}</p>
142
<p>Double: {{ doubleCount }}</p>
143
<p>User: {{ username }}</p>
144
<p>Even: {{ isEven }}</p>
145
</div>
146
`,
147
};
148
```
149
150
### Map Writable State
151
152
Maps store state properties as writable computed properties, allowing two-way binding with v-model.
153
154
```typescript { .api }
155
/**
156
* Maps store state properties as writable computed properties
157
* @param useStore - Store definition to map from
158
* @param keys - Array of state property keys to map as writable
159
* @returns Object with writable computed properties
160
*/
161
function mapWritableState<
162
Id extends string,
163
S extends StateTree,
164
G extends _GettersTree<S>,
165
A,
166
Keys extends keyof S
167
>(
168
useStore: StoreDefinition<Id, S, G, A>,
169
keys: readonly Keys[]
170
): _MapWritableStateReturn<S, Keys>;
171
172
/**
173
* Maps store state properties as writable with custom names
174
* @param useStore - Store definition to map from
175
* @param keysObject - Object mapping local names to store state properties
176
* @returns Object with writable computed properties
177
*/
178
function mapWritableState<
179
Id extends string,
180
S extends StateTree,
181
G extends _GettersTree<S>,
182
A
183
>(
184
useStore: StoreDefinition<Id, S, G, A>,
185
keysObject: Record<string, keyof S>
186
): _MapWritableStateObjectReturn<S>;
187
188
type _MapWritableStateReturn<S, Keys extends keyof S> = {
189
[K in Keys]: {
190
get(): S[K];
191
set(value: S[K]): void;
192
};
193
};
194
195
type _MapWritableStateObjectReturn<S> = Record<string, {
196
get(): any;
197
set(value: any): void;
198
}>;
199
```
200
201
**Usage Examples:**
202
203
```typescript
204
import { mapWritableState } from "pinia";
205
import { useFormStore } from "./stores/form";
206
import { useSettingsStore } from "./stores/settings";
207
208
export default {
209
computed: {
210
// Direct writable mapping
211
...mapWritableState(useFormStore, ["name", "email", "message"]),
212
213
// Custom names
214
...mapWritableState(useSettingsStore, {
215
darkMode: "isDarkMode",
216
lang: "language",
217
}),
218
},
219
template: `
220
<form>
221
<!-- Two-way binding with store state -->
222
<input v-model="name" placeholder="Name" />
223
<input v-model="email" placeholder="Email" />
224
<textarea v-model="message" placeholder="Message"></textarea>
225
226
<!-- Settings -->
227
<label>
228
<input type="checkbox" v-model="darkMode" />
229
Dark Mode
230
</label>
231
<select v-model="lang">
232
<option value="en">English</option>
233
<option value="es">Spanish</option>
234
</select>
235
</form>
236
`,
237
};
238
```
239
240
### Map Getters
241
242
Maps store getters to component computed properties. This is an alias for `mapState` but specifically for getters.
243
244
```typescript { .api }
245
/**
246
* Maps store getters to component computed properties
247
* @param useStore - Store definition to map from
248
* @param keys - Array of getter keys to map
249
* @returns Object with reactive computed properties
250
*/
251
function mapGetters<
252
Id extends string,
253
S extends StateTree,
254
G extends _GettersTree<S>,
255
A,
256
Keys extends keyof G
257
>(
258
useStore: StoreDefinition<Id, S, G, A>,
259
keys: readonly Keys[]
260
): _MapStateReturn<G, Keys>;
261
```
262
263
**Usage Examples:**
264
265
```typescript
266
import { mapGetters } from "pinia";
267
import { useCounterStore } from "./stores/counter";
268
269
export default {
270
computed: {
271
...mapGetters(useCounterStore, ["doubleCount", "isEven", "displayName"]),
272
},
273
template: `
274
<div>
275
<p>Double Count: {{ doubleCount }}</p>
276
<p>Is Even: {{ isEven ? 'Yes' : 'No' }}</p>
277
<p>Display: {{ displayName }}</p>
278
</div>
279
`,
280
};
281
```
282
283
### Map Actions
284
285
Maps store actions to component methods, providing direct access to store methods.
286
287
```typescript { .api }
288
/**
289
* Maps store actions to component methods
290
* @param useStore - Store definition to map from
291
* @param keys - Array of action keys to map
292
* @returns Object with action methods
293
*/
294
function mapActions<
295
Id extends string,
296
S extends StateTree,
297
G extends _GettersTree<S>,
298
A,
299
Keys extends keyof A
300
>(
301
useStore: StoreDefinition<Id, S, G, A>,
302
keys: readonly Keys[]
303
): _MapActionsReturn<A, Keys>;
304
305
/**
306
* Maps store actions with custom names
307
* @param useStore - Store definition to map from
308
* @param keysObject - Object mapping local names to action names
309
* @returns Object with action methods
310
*/
311
function mapActions<
312
Id extends string,
313
S extends StateTree,
314
G extends _GettersTree<S>,
315
A
316
>(
317
useStore: StoreDefinition<Id, S, G, A>,
318
keysObject: Record<string, keyof A>
319
): _MapActionsObjectReturn<A>;
320
321
type _MapActionsReturn<A, Keys extends keyof A> = {
322
[K in Keys]: A[K];
323
};
324
325
type _MapActionsObjectReturn<A> = Record<string, any>;
326
```
327
328
**Usage Examples:**
329
330
```typescript
331
import { mapActions } from "pinia";
332
import { useCounterStore } from "./stores/counter";
333
import { useUserStore } from "./stores/user";
334
335
export default {
336
methods: {
337
// Direct action mapping
338
...mapActions(useCounterStore, ["increment", "decrement", "reset"]),
339
340
// Custom names
341
...mapActions(useUserStore, {
342
signIn: "login",
343
signOut: "logout",
344
updateProfile: "updateUser",
345
}),
346
347
// Use in component methods
348
handleIncrement() {
349
this.increment(); // Calls store action
350
},
351
352
async handleLogin() {
353
try {
354
await this.signIn({ email: this.email, password: this.password });
355
this.$router.push("/dashboard");
356
} catch (error) {
357
this.showError(error.message);
358
}
359
},
360
},
361
template: `
362
<div>
363
<button @click="increment">+</button>
364
<button @click="decrement">-</button>
365
<button @click="reset">Reset</button>
366
<button @click="handleLogin">Login</button>
367
</div>
368
`,
369
};
370
```
371
372
### Set Map Store Suffix
373
374
Customizes the suffix used by `mapStores` when creating computed property names.
375
376
```typescript { .api }
377
/**
378
* Sets the suffix for store names in mapStores
379
* @param suffix - New suffix to use (default is "Store")
380
*/
381
function setMapStoreSuffix(suffix: string): void;
382
383
interface MapStoresCustomization {
384
suffix?: string;
385
}
386
```
387
388
**Usage Examples:**
389
390
```typescript
391
import { setMapStoreSuffix, mapStores } from "pinia";
392
import { useUserStore } from "./stores/user";
393
394
// Default behavior
395
export default {
396
computed: {
397
...mapStores(useUserStore), // Creates 'userStore' computed property
398
},
399
};
400
401
// Custom suffix
402
setMapStoreSuffix("Repository");
403
404
export default {
405
computed: {
406
...mapStores(useUserStore), // Creates 'userRepository' computed property
407
},
408
};
409
410
// Empty suffix
411
setMapStoreSuffix("");
412
413
export default {
414
computed: {
415
...mapStores(useUserStore), // Creates 'user' computed property
416
},
417
};
418
419
// Reset to default
420
setMapStoreSuffix("Store");
421
```
422
423
## Complete Options API Example
424
425
```typescript
426
import { mapStores, mapState, mapWritableState, mapActions } from "pinia";
427
import { useCounterStore } from "./stores/counter";
428
import { useUserStore } from "./stores/user";
429
import { useCartStore } from "./stores/cart";
430
431
export default {
432
computed: {
433
// Store instances
434
...mapStores(useCounterStore, useUserStore, useCartStore),
435
436
// Read-only state
437
...mapState(useCounterStore, ["count", "doubleCount"]),
438
...mapState(useUserStore, ["currentUser", "isLoggedIn"]),
439
440
// Writable state for forms
441
...mapWritableState(useUserStore, ["email", "preferences"]),
442
443
// Custom computed
444
canPurchase() {
445
return this.isLoggedIn && this.cartStore.items.length > 0;
446
},
447
},
448
449
methods: {
450
// Store actions
451
...mapActions(useCounterStore, ["increment", "reset"]),
452
...mapActions(useUserStore, {
453
signIn: "login",
454
signOut: "logout",
455
}),
456
...mapActions(useCartStore, ["addItem", "removeItem", "checkout"]),
457
458
// Component methods
459
async handleCheckout() {
460
if (this.canPurchase) {
461
await this.checkout();
462
this.reset(); // Reset counter after purchase
463
}
464
},
465
},
466
467
template: `
468
<div>
469
<p>Count: {{ count }} ({{ doubleCount }})</p>
470
<button @click="increment">+</button>
471
472
<div v-if="isLoggedIn">
473
<p>Welcome {{ currentUser.name }}!</p>
474
<input v-model="email" placeholder="Email" />
475
<button @click="handleCheckout" :disabled="!canPurchase">
476
Checkout
477
</button>
478
</div>
479
480
<button v-else @click="signIn">Sign In</button>
481
</div>
482
`,
483
};
484
```
485
486
## Types
487
488
```typescript { .api }
489
type _GettersTree<S extends StateTree> = Record<
490
string,
491
((state: UnwrapRef<S> & UnwrapRef<PiniaCustomStateProperties>) => any) | (() => any)
492
>;
493
```