0
# Store Definition
1
2
Functions for defining stores with both composition API (setup function) and options API syntax, providing flexible patterns for different development preferences.
3
4
## Capabilities
5
6
### Define Store with Options API
7
8
Creates a store definition using the options API syntax with explicit state, getters, and actions properties.
9
10
```typescript { .api }
11
/**
12
* Creates a store definition using options API syntax
13
* @param id - Unique identifier for the store
14
* @param options - Store configuration with state, getters, and actions
15
* @returns Store definition function that creates store instances
16
*/
17
function defineStore<
18
Id extends string,
19
S extends StateTree = {},
20
G extends _GettersTree<S> = {},
21
A = {}
22
>(
23
id: Id,
24
options: Omit<DefineStoreOptions<Id, S, G, A>, 'id'>
25
): StoreDefinition<Id, S, G, A>;
26
27
interface DefineStoreOptions<Id extends string, S extends StateTree, G extends _GettersTree<S>, A> {
28
/** Unique store identifier */
29
id: Id;
30
/** Function that returns the initial state */
31
state?: () => S;
32
/** Object containing getter functions */
33
getters?: G & _GettersTree<S>;
34
/** Object containing action methods */
35
actions?: A & _ActionsTree;
36
/** Hydration function for SSR */
37
hydrate?(storeState: UnwrapRef<S>, initialState: UnwrapRef<S>): void;
38
}
39
```
40
41
**Usage Examples:**
42
43
```typescript
44
import { defineStore } from "pinia";
45
46
// Basic options store
47
const useCounterStore = defineStore("counter", {
48
state: () => ({
49
count: 0,
50
name: "Counter",
51
}),
52
getters: {
53
doubleCount: (state) => state.count * 2,
54
displayName: (state) => `${state.name}: ${state.count}`,
55
},
56
actions: {
57
increment() {
58
this.count++;
59
},
60
setName(newName: string) {
61
this.name = newName;
62
},
63
async fetchInitialData() {
64
const response = await fetch("/api/counter");
65
const data = await response.json();
66
this.count = data.count;
67
},
68
},
69
});
70
71
// Store with complex state and getters
72
const useUserStore = defineStore("user", {
73
state: () => ({
74
users: [] as User[],
75
currentUserId: null as string | null,
76
loading: false,
77
}),
78
getters: {
79
currentUser: (state) =>
80
state.users.find(user => user.id === state.currentUserId),
81
activeUsers: (state) =>
82
state.users.filter(user => user.active),
83
getUserById: (state) => {
84
return (userId: string) => state.users.find(user => user.id === userId);
85
},
86
},
87
actions: {
88
async loadUsers() {
89
this.loading = true;
90
try {
91
const users = await fetchUsers();
92
this.users = users;
93
} finally {
94
this.loading = false;
95
}
96
},
97
setCurrentUser(userId: string) {
98
this.currentUserId = userId;
99
},
100
},
101
});
102
```
103
104
### Define Store with Setup Function
105
106
Creates a store definition using the composition API syntax with a setup function that returns the store's reactive state, computed properties, and methods.
107
108
```typescript { .api }
109
/**
110
* Creates a store definition using composition API setup function
111
* @param id - Unique identifier for the store
112
* @param storeSetup - Setup function that defines the store logic
113
* @param options - Additional options for the setup store
114
* @returns Store definition function that creates store instances
115
*/
116
function defineStore<Id extends string, SS>(
117
id: Id,
118
storeSetup: () => SS,
119
options?: DefineSetupStoreOptions<
120
Id,
121
_ExtractStateFromSetupStore<SS>,
122
_ExtractGettersFromSetupStore<SS>,
123
_ExtractActionsFromSetupStore<SS>
124
>
125
): StoreDefinition<
126
Id,
127
_ExtractStateFromSetupStore<SS>,
128
_ExtractGettersFromSetupStore<SS>,
129
_ExtractActionsFromSetupStore<SS>
130
>;
131
132
interface DefineSetupStoreOptions<Id extends string, S extends StateTree, G, A> {
133
/** Hydration function for SSR */
134
hydrate?(storeState: UnwrapRef<S>, initialState: UnwrapRef<S>): void;
135
/** Actions that should be serialized for devtools */
136
actions?: Record<string, any>;
137
}
138
```
139
140
**Usage Examples:**
141
142
```typescript
143
import { defineStore } from "pinia";
144
import { ref, computed } from "vue";
145
146
// Basic setup store
147
const useCounterStore = defineStore("counter", () => {
148
// State (equivalent to state in options API)
149
const count = ref(0);
150
const name = ref("Counter");
151
152
// Getters (equivalent to getters in options API)
153
const doubleCount = computed(() => count.value * 2);
154
const displayName = computed(() => `${name.value}: ${count.value}`);
155
156
// Actions (equivalent to actions in options API)
157
function increment() {
158
count.value++;
159
}
160
161
function setName(newName: string) {
162
name.value = newName;
163
}
164
165
async function fetchInitialData() {
166
const response = await fetch("/api/counter");
167
const data = await response.json();
168
count.value = data.count;
169
}
170
171
// Return all state, getters, and actions
172
return {
173
count,
174
name,
175
doubleCount,
176
displayName,
177
increment,
178
setName,
179
fetchInitialData,
180
};
181
});
182
183
// Advanced setup store with complex logic
184
const useTaskStore = defineStore("tasks", () => {
185
const tasks = ref<Task[]>([]);
186
const filter = ref<"all" | "active" | "completed">("all");
187
const loading = ref(false);
188
189
// Computed properties
190
const filteredTasks = computed(() => {
191
switch (filter.value) {
192
case "active":
193
return tasks.value.filter(task => !task.completed);
194
case "completed":
195
return tasks.value.filter(task => task.completed);
196
default:
197
return tasks.value;
198
}
199
});
200
201
const taskStats = computed(() => ({
202
total: tasks.value.length,
203
active: tasks.value.filter(t => !t.completed).length,
204
completed: tasks.value.filter(t => t.completed).length,
205
}));
206
207
// Actions
208
async function loadTasks() {
209
loading.value = true;
210
try {
211
const response = await fetch("/api/tasks");
212
tasks.value = await response.json();
213
} finally {
214
loading.value = false;
215
}
216
}
217
218
function addTask(title: string) {
219
tasks.value.push({
220
id: Date.now().toString(),
221
title,
222
completed: false,
223
createdAt: new Date(),
224
});
225
}
226
227
function toggleTask(id: string) {
228
const task = tasks.value.find(t => t.id === id);
229
if (task) {
230
task.completed = !task.completed;
231
}
232
}
233
234
function setFilter(newFilter: typeof filter.value) {
235
filter.value = newFilter;
236
}
237
238
return {
239
// State
240
tasks: readonly(tasks),
241
filter,
242
loading,
243
// Getters
244
filteredTasks,
245
taskStats,
246
// Actions
247
loadTasks,
248
addTask,
249
toggleTask,
250
setFilter,
251
};
252
});
253
```
254
255
### Setup Store with Options
256
257
Setup stores can include additional options for hydration and action configuration.
258
259
```typescript { .api }
260
const useAdvancedStore = defineStore("advanced", () => {
261
const data = ref<any>(null);
262
263
function updateData(newData: any) {
264
data.value = newData;
265
}
266
267
return { data, updateData };
268
}, {
269
// Custom hydration logic for SSR
270
hydrate(storeState, initialState) {
271
storeState.data = initialState.data;
272
},
273
});
274
```
275
276
## Store Definition Types
277
278
```typescript { .api }
279
type StoreDefinition<Id extends string = string, S extends StateTree = {}, G = {}, A = {}> =
280
() => Store<Id, S, G, A>;
281
282
type _GettersTree<S extends StateTree> = Record<
283
string,
284
((state: UnwrapRef<S> & UnwrapRef<PiniaCustomStateProperties>) => any) | (() => any)
285
>;
286
287
type _ActionsTree = Record<string, _Method>;
288
289
type _Method = (...args: any[]) => any;
290
291
// Extraction types for setup stores
292
type _ExtractStateFromSetupStore<SS> = SS extends undefined | void
293
? {}
294
: _ExtractStateFromSetupStore_Keys<SS> extends keyof SS
295
? Pick<SS, _ExtractStateFromSetupStore_Keys<SS>>
296
: never;
297
298
type _ExtractGettersFromSetupStore<SS> = SS extends undefined | void
299
? {}
300
: _ExtractGettersFromSetupStore_Keys<SS> extends keyof SS
301
? Pick<SS, _ExtractGettersFromSetupStore_Keys<SS>>
302
: never;
303
304
type _ExtractActionsFromSetupStore<SS> = SS extends undefined | void
305
? {}
306
: _ExtractActionsFromSetupStore_Keys<SS> extends keyof SS
307
? Pick<SS, _ExtractActionsFromSetupStore_Keys<SS>>
308
: never;
309
```