@dxtmisha/wiki 0.24.0 → 0.24.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/media/functional/en/about.mdx +55 -0
- package/src/media/functional/en/dataStorage.mdx +61 -83
- package/src/media/functional/en/useApiRef.mdx +517 -0
- package/src/media/functional/en/useBroadcastValueRef.mdx +344 -0
- package/src/media/functional/en/useCookieRef.mdx +348 -0
- package/src/media/functional/en/useGeoIntlRef.mdx +288 -0
- package/src/media/functional/en/useHashRef.mdx +302 -0
- package/src/media/functional/en/useLazyRef.mdx +329 -0
- package/src/media/functional/en/useLoadingRef.mdx +159 -0
- package/src/media/functional/en/useSessionRef.mdx +248 -0
- package/src/media/functional/en/useStorageRef.mdx +242 -0
- package/src/media/functional/en/useTranslateRef.mdx +312 -0
- package/src/media/functional/ru/about.mdx +55 -0
- package/src/media/functional/ru/dataStorage.mdx +59 -81
- package/src/media/functional/ru/useApiRef.mdx +517 -0
- package/src/media/functional/ru/useBroadcastValueRef.mdx +344 -0
- package/src/media/functional/ru/useCookieRef.mdx +348 -0
- package/src/media/functional/ru/useGeoIntlRef.mdx +288 -0
- package/src/media/functional/ru/useHashRef.mdx +302 -0
- package/src/media/functional/ru/useLazyRef.mdx +329 -0
- package/src/media/functional/ru/useLoadingRef.mdx +159 -0
- package/src/media/functional/ru/useSessionRef.mdx +248 -0
- package/src/media/functional/ru/useStorageRef.mdx +242 -0
- package/src/media/functional/ru/useTranslateRef.mdx +312 -0
|
@@ -0,0 +1,517 @@
|
|
|
1
|
+
import {Meta} from '@storybook/addon-docs/blocks'
|
|
2
|
+
|
|
3
|
+
<Meta title='@dxtmisha/functional/en/Composables/useApiRef'/>
|
|
4
|
+
|
|
5
|
+
# Composable useApiRef
|
|
6
|
+
|
|
7
|
+
Composable for working with HTTP requests in Vue 3 applications. Provides reactive interface for executing API requests with automatic loading state management, reactive parameters support, conditional execution, and data transformation.
|
|
8
|
+
|
|
9
|
+
## Key Features
|
|
10
|
+
|
|
11
|
+
- **Reactive requests** — automatic request execution when parameters change
|
|
12
|
+
- **State management** — automatic tracking of loading state and data readiness
|
|
13
|
+
- **Conditional execution** — ability to execute requests only when conditions are met
|
|
14
|
+
- **Data transformation** — transform received data before storing
|
|
15
|
+
- **Api integration** — uses Api class for request execution with caching support
|
|
16
|
+
- **Global conditions** — ability to set global conditions for all useApiRef instances
|
|
17
|
+
- **Auto cleanup** — optional data cleanup on component unmount
|
|
18
|
+
- **TypeScript support** — full typing with generics
|
|
19
|
+
|
|
20
|
+
## Basic Usage
|
|
21
|
+
|
|
22
|
+
### Simple GET Request
|
|
23
|
+
|
|
24
|
+
```javascript
|
|
25
|
+
import { useApiRef } from '@dxtmisha/functional'
|
|
26
|
+
|
|
27
|
+
// Executes GET request on component mount
|
|
28
|
+
const { data, loading, isStarting, reading } = useApiRef('/api/users')
|
|
29
|
+
|
|
30
|
+
// data - ref with response data
|
|
31
|
+
// loading - ref with loading state
|
|
32
|
+
// isStarting - computed, true before first data load
|
|
33
|
+
// reading - computed, true while reading data
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Component Usage
|
|
37
|
+
|
|
38
|
+
```vue
|
|
39
|
+
<script setup>
|
|
40
|
+
import { useApiRef } from '@dxtmisha/functional'
|
|
41
|
+
|
|
42
|
+
const { data: users, loading } = useApiRef('/api/users')
|
|
43
|
+
</script>
|
|
44
|
+
|
|
45
|
+
<template>
|
|
46
|
+
<div v-if="loading">Loading...</div>
|
|
47
|
+
<div v-else-if="users">
|
|
48
|
+
<div v-for="user in users" :key="user.id">
|
|
49
|
+
{{ user.name }}
|
|
50
|
+
</div>
|
|
51
|
+
</div>
|
|
52
|
+
</template>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Parameters
|
|
56
|
+
|
|
57
|
+
### `path`
|
|
58
|
+
|
|
59
|
+
Path to API endpoint. Can be a string or ref for reactivity.
|
|
60
|
+
|
|
61
|
+
**Type:** `RefOrNormal<string | undefined>`
|
|
62
|
+
|
|
63
|
+
```javascript
|
|
64
|
+
// Static path
|
|
65
|
+
const { data } = useApiRef('/api/users')
|
|
66
|
+
|
|
67
|
+
// Reactive path
|
|
68
|
+
const userId = ref(1)
|
|
69
|
+
const { data: user } = useApiRef(computed(() => `/api/users/${userId.value}`))
|
|
70
|
+
|
|
71
|
+
// New request executes automatically when userId changes
|
|
72
|
+
userId.value = 2
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### `options`
|
|
76
|
+
|
|
77
|
+
Request parameters. Can be HTTP method, settings object, or ref.
|
|
78
|
+
|
|
79
|
+
**Type:** `ApiMethodItem | RefOrNormal<ApiFetch>`
|
|
80
|
+
|
|
81
|
+
```javascript
|
|
82
|
+
// Specify method only
|
|
83
|
+
const { data } = useApiRef('/api/users', 'POST')
|
|
84
|
+
|
|
85
|
+
// Full settings
|
|
86
|
+
const { data } = useApiRef('/api/users', {
|
|
87
|
+
method: 'POST',
|
|
88
|
+
request: { name: 'John', email: 'john@example.com' },
|
|
89
|
+
headers: { 'Content-Type': 'application/json' }
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
// Reactive parameters
|
|
93
|
+
const params = ref({ page: 1, limit: 10 })
|
|
94
|
+
const { data } = useApiRef('/api/users', computed(() => ({
|
|
95
|
+
method: 'GET',
|
|
96
|
+
request: params.value
|
|
97
|
+
})))
|
|
98
|
+
|
|
99
|
+
// New request on params change
|
|
100
|
+
params.value = { page: 2, limit: 10 }
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### `reactivity`
|
|
104
|
+
|
|
105
|
+
Enable or disable automatic execution on parameter changes.
|
|
106
|
+
|
|
107
|
+
**Type:** `boolean`
|
|
108
|
+
**Default:** `true`
|
|
109
|
+
|
|
110
|
+
```javascript
|
|
111
|
+
// With reactivity (default)
|
|
112
|
+
const params = ref({ page: 1 })
|
|
113
|
+
const { data, reset } = useApiRef('/api/users', { request: params }, true)
|
|
114
|
+
|
|
115
|
+
params.value.page = 2 // Request executes automatically
|
|
116
|
+
|
|
117
|
+
// Without reactivity
|
|
118
|
+
const { data, reset } = useApiRef('/api/users', { request: params }, false)
|
|
119
|
+
|
|
120
|
+
params.value.page = 2 // Request does NOT execute
|
|
121
|
+
await reset() // Need to call reset manually
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### `conditions`
|
|
125
|
+
|
|
126
|
+
Condition for request execution. Request executes only if condition is true.
|
|
127
|
+
|
|
128
|
+
**Type:** `RefType<boolean>`
|
|
129
|
+
|
|
130
|
+
```javascript
|
|
131
|
+
// Request executes only when isAuth === true
|
|
132
|
+
const isAuth = ref(false)
|
|
133
|
+
const { data } = useApiRef('/api/profile', undefined, true, isAuth)
|
|
134
|
+
|
|
135
|
+
// data will be undefined while isAuth === false
|
|
136
|
+
console.log(data.value) // undefined
|
|
137
|
+
|
|
138
|
+
isAuth.value = true // Request executes automatically
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### `transformation`
|
|
142
|
+
|
|
143
|
+
Function to transform received data before storing in ref.
|
|
144
|
+
|
|
145
|
+
**Type:** `(data: T) => R`
|
|
146
|
+
|
|
147
|
+
```javascript
|
|
148
|
+
// Transform API data to needed format
|
|
149
|
+
const { data } = useApiRef(
|
|
150
|
+
'/api/users',
|
|
151
|
+
undefined,
|
|
152
|
+
true,
|
|
153
|
+
undefined,
|
|
154
|
+
(response) => {
|
|
155
|
+
// response - data from API
|
|
156
|
+
// Return transformed data
|
|
157
|
+
return response.data.map(user => ({
|
|
158
|
+
id: user.id,
|
|
159
|
+
fullName: `${user.firstName} ${user.lastName}`,
|
|
160
|
+
isActive: user.status === 'active'
|
|
161
|
+
}))
|
|
162
|
+
}
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
// data contains transformed data
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### `unmounted`
|
|
169
|
+
|
|
170
|
+
Whether to clear data on component unmount.
|
|
171
|
+
|
|
172
|
+
**Type:** `boolean`
|
|
173
|
+
**Default:** `undefined`
|
|
174
|
+
|
|
175
|
+
```javascript
|
|
176
|
+
// Data will be cleared on component unmount
|
|
177
|
+
const { data } = useApiRef('/api/users', undefined, true, undefined, undefined, true)
|
|
178
|
+
|
|
179
|
+
// On page navigation, data becomes undefined
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Return Values
|
|
183
|
+
|
|
184
|
+
### `data`
|
|
185
|
+
|
|
186
|
+
Ref with response data. `undefined` before first load.
|
|
187
|
+
|
|
188
|
+
**Type:** `Ref<R | undefined>`
|
|
189
|
+
|
|
190
|
+
```javascript
|
|
191
|
+
const { data } = useApiRef('/api/users')
|
|
192
|
+
|
|
193
|
+
console.log(data.value) // undefined before load
|
|
194
|
+
// After load: array of users
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### `loading`
|
|
198
|
+
|
|
199
|
+
Ref with loading state. `true` during request execution.
|
|
200
|
+
|
|
201
|
+
**Type:** `Ref<boolean>`
|
|
202
|
+
|
|
203
|
+
```javascript
|
|
204
|
+
const { loading } = useApiRef('/api/users')
|
|
205
|
+
|
|
206
|
+
console.log(loading.value) // true during load, false after
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### `isStarting`
|
|
210
|
+
|
|
211
|
+
Computed showing if data has been loaded at least once. `true` before first load.
|
|
212
|
+
|
|
213
|
+
**Type:** `ComputedRef<boolean>`
|
|
214
|
+
|
|
215
|
+
```javascript
|
|
216
|
+
const { data, isStarting } = useApiRef('/api/users')
|
|
217
|
+
|
|
218
|
+
console.log(isStarting.value) // true before first load
|
|
219
|
+
// After first load always false, even on subsequent requests
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### `reading`
|
|
223
|
+
|
|
224
|
+
Computed showing active data reading.
|
|
225
|
+
|
|
226
|
+
**Type:** `ComputedRef<boolean>`
|
|
227
|
+
|
|
228
|
+
```javascript
|
|
229
|
+
const { reading } = useApiRef('/api/users')
|
|
230
|
+
|
|
231
|
+
console.log(reading.value) // true while reading data
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### `reset`
|
|
235
|
+
|
|
236
|
+
Function to force request execution.
|
|
237
|
+
|
|
238
|
+
**Type:** `() => Promise<void>`
|
|
239
|
+
|
|
240
|
+
```javascript
|
|
241
|
+
const { data, reset } = useApiRef('/api/users')
|
|
242
|
+
|
|
243
|
+
// Force reload data
|
|
244
|
+
await reset()
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
## Usage Examples
|
|
248
|
+
|
|
249
|
+
### List with Filters
|
|
250
|
+
|
|
251
|
+
```vue
|
|
252
|
+
<script setup>
|
|
253
|
+
import { ref, computed } from 'vue'
|
|
254
|
+
import { useApiRef } from '@dxtmisha/functional'
|
|
255
|
+
|
|
256
|
+
const searchQuery = ref('')
|
|
257
|
+
const currentPage = ref(1)
|
|
258
|
+
|
|
259
|
+
const { data: users, loading } = useApiRef(
|
|
260
|
+
'/api/users',
|
|
261
|
+
computed(() => ({
|
|
262
|
+
method: 'GET',
|
|
263
|
+
request: {
|
|
264
|
+
search: searchQuery.value,
|
|
265
|
+
page: currentPage.value,
|
|
266
|
+
limit: 20
|
|
267
|
+
}
|
|
268
|
+
}))
|
|
269
|
+
)
|
|
270
|
+
|
|
271
|
+
const handleSearch = (query) => {
|
|
272
|
+
searchQuery.value = query
|
|
273
|
+
currentPage.value = 1 // Reset to first page
|
|
274
|
+
// Request executes automatically
|
|
275
|
+
}
|
|
276
|
+
</script>
|
|
277
|
+
|
|
278
|
+
<template>
|
|
279
|
+
<div>
|
|
280
|
+
<input v-model="searchQuery" placeholder="Search...">
|
|
281
|
+
<div v-if="loading">Loading...</div>
|
|
282
|
+
<div v-else>
|
|
283
|
+
<div v-for="user in users" :key="user.id">{{ user.name }}</div>
|
|
284
|
+
<button @click="currentPage++">Next page</button>
|
|
285
|
+
</div>
|
|
286
|
+
</div>
|
|
287
|
+
</template>
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
### Conditional Loading
|
|
291
|
+
|
|
292
|
+
```vue
|
|
293
|
+
<script setup>
|
|
294
|
+
import { ref } from 'vue'
|
|
295
|
+
import { useApiRef } from '@dxtmisha/functional'
|
|
296
|
+
|
|
297
|
+
const showDetails = ref(false)
|
|
298
|
+
const userId = ref(1)
|
|
299
|
+
|
|
300
|
+
// Data loads only when showDetails === true
|
|
301
|
+
const { data: userDetails, loading } = useApiRef(
|
|
302
|
+
computed(() => `/api/users/${userId.value}/details`),
|
|
303
|
+
undefined,
|
|
304
|
+
true,
|
|
305
|
+
showDetails
|
|
306
|
+
)
|
|
307
|
+
|
|
308
|
+
const toggleDetails = () => {
|
|
309
|
+
showDetails.value = !showDetails.value
|
|
310
|
+
// If showDetails becomes true, request executes automatically
|
|
311
|
+
}
|
|
312
|
+
</script>
|
|
313
|
+
|
|
314
|
+
<template>
|
|
315
|
+
<button @click="toggleDetails">
|
|
316
|
+
{{ showDetails ? 'Hide' : 'Show' }} details
|
|
317
|
+
</button>
|
|
318
|
+
<div v-if="showDetails">
|
|
319
|
+
<div v-if="loading">Loading details...</div>
|
|
320
|
+
<div v-else-if="userDetails">{{ userDetails }}</div>
|
|
321
|
+
</div>
|
|
322
|
+
</template>
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
### POST Request with Transformation
|
|
326
|
+
|
|
327
|
+
```vue
|
|
328
|
+
<script setup>
|
|
329
|
+
import { ref } from 'vue'
|
|
330
|
+
import { useApiRef } from '@dxtmisha/functional'
|
|
331
|
+
|
|
332
|
+
const formData = ref({
|
|
333
|
+
firstName: '',
|
|
334
|
+
lastName: '',
|
|
335
|
+
email: ''
|
|
336
|
+
})
|
|
337
|
+
|
|
338
|
+
const { data: createdUser, loading, reset } = useApiRef(
|
|
339
|
+
'/api/users',
|
|
340
|
+
{
|
|
341
|
+
method: 'POST',
|
|
342
|
+
request: formData
|
|
343
|
+
},
|
|
344
|
+
false, // Disable automatic execution
|
|
345
|
+
undefined,
|
|
346
|
+
(response) => {
|
|
347
|
+
// Transform API response
|
|
348
|
+
return {
|
|
349
|
+
id: response.id,
|
|
350
|
+
fullName: `${response.firstName} ${response.lastName}`,
|
|
351
|
+
email: response.email,
|
|
352
|
+
createdAt: new Date(response.created_at)
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
)
|
|
356
|
+
|
|
357
|
+
const handleSubmit = async () => {
|
|
358
|
+
await reset() // Execute request manually
|
|
359
|
+
if (createdUser.value) {
|
|
360
|
+
console.log('User created:', createdUser.value)
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
</script>
|
|
364
|
+
|
|
365
|
+
<template>
|
|
366
|
+
<form @submit.prevent="handleSubmit">
|
|
367
|
+
<input v-model="formData.firstName" placeholder="First name">
|
|
368
|
+
<input v-model="formData.lastName" placeholder="Last name">
|
|
369
|
+
<input v-model="formData.email" placeholder="Email">
|
|
370
|
+
<button :disabled="loading">
|
|
371
|
+
{{ loading ? 'Submitting...' : 'Create' }}
|
|
372
|
+
</button>
|
|
373
|
+
</form>
|
|
374
|
+
</template>
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
### Multiple Requests
|
|
378
|
+
|
|
379
|
+
```vue
|
|
380
|
+
<script setup>
|
|
381
|
+
import { useApiRef } from '@dxtmisha/functional'
|
|
382
|
+
|
|
383
|
+
const { data: users, loading: usersLoading } = useApiRef('/api/users')
|
|
384
|
+
const { data: posts, loading: postsLoading } = useApiRef('/api/posts')
|
|
385
|
+
const { data: comments, loading: commentsLoading } = useApiRef('/api/comments')
|
|
386
|
+
|
|
387
|
+
const isLoading = computed(() =>
|
|
388
|
+
usersLoading.value || postsLoading.value || commentsLoading.value
|
|
389
|
+
)
|
|
390
|
+
</script>
|
|
391
|
+
|
|
392
|
+
<template>
|
|
393
|
+
<div v-if="isLoading">Loading data...</div>
|
|
394
|
+
<div v-else>
|
|
395
|
+
<section>
|
|
396
|
+
<h2>Users</h2>
|
|
397
|
+
<div v-for="user in users" :key="user.id">{{ user.name }}</div>
|
|
398
|
+
</section>
|
|
399
|
+
<section>
|
|
400
|
+
<h2>Posts</h2>
|
|
401
|
+
<div v-for="post in posts" :key="post.id">{{ post.title }}</div>
|
|
402
|
+
</section>
|
|
403
|
+
<section>
|
|
404
|
+
<h2>Comments</h2>
|
|
405
|
+
<div v-for="comment in comments" :key="comment.id">{{ comment.text }}</div>
|
|
406
|
+
</section>
|
|
407
|
+
</div>
|
|
408
|
+
</template>
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
## Global Conditions
|
|
412
|
+
|
|
413
|
+
The `setApiRefGlobalConditions` function allows setting a global condition for all useApiRef instances.
|
|
414
|
+
|
|
415
|
+
```javascript
|
|
416
|
+
import { setApiRefGlobalConditions, useApiRef } from '@dxtmisha/functional'
|
|
417
|
+
import { ref } from 'vue'
|
|
418
|
+
|
|
419
|
+
// Global condition - e.g., authentication status
|
|
420
|
+
const isAuthenticated = ref(false)
|
|
421
|
+
setApiRefGlobalConditions(isAuthenticated)
|
|
422
|
+
|
|
423
|
+
// Now all useApiRef will consider this condition
|
|
424
|
+
const { data: profile } = useApiRef('/api/profile')
|
|
425
|
+
const { data: settings } = useApiRef('/api/settings')
|
|
426
|
+
|
|
427
|
+
// Requests won't execute while isAuthenticated === false
|
|
428
|
+
isAuthenticated.value = true // All requests execute automatically
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
## Integration with Api Class
|
|
432
|
+
|
|
433
|
+
useApiRef uses the Api class, so all Api settings apply automatically:
|
|
434
|
+
|
|
435
|
+
```javascript
|
|
436
|
+
import { Api, useApiRef } from '@dxtmisha/functional'
|
|
437
|
+
|
|
438
|
+
// Configure base URL and headers
|
|
439
|
+
Api.setUrl('/api/v1/')
|
|
440
|
+
Api.setHeaders({
|
|
441
|
+
'Authorization': 'Bearer token123',
|
|
442
|
+
'Accept': 'application/json'
|
|
443
|
+
})
|
|
444
|
+
|
|
445
|
+
// useApiRef automatically uses these settings
|
|
446
|
+
const { data } = useApiRef('/users') // Request to /api/v1/users with headers
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
## TypeScript
|
|
450
|
+
|
|
451
|
+
```typescript
|
|
452
|
+
interface User {
|
|
453
|
+
id: number
|
|
454
|
+
name: string
|
|
455
|
+
email: string
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
interface ApiResponse<T> {
|
|
459
|
+
data: T[]
|
|
460
|
+
total: number
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
// Type response data
|
|
464
|
+
const { data } = useApiRef<User[]>('/api/users')
|
|
465
|
+
|
|
466
|
+
// Type with transformation
|
|
467
|
+
const { data } = useApiRef<User[], ApiResponse<User>>(
|
|
468
|
+
'/api/users',
|
|
469
|
+
undefined,
|
|
470
|
+
true,
|
|
471
|
+
undefined,
|
|
472
|
+
(response) => response.data // response typed as ApiResponse<User>
|
|
473
|
+
)
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
## Behavior Features
|
|
477
|
+
|
|
478
|
+
### Lazy Initialization
|
|
479
|
+
|
|
480
|
+
Request doesn't execute until first access to `data`:
|
|
481
|
+
|
|
482
|
+
```javascript
|
|
483
|
+
const api = useApiRef('/api/users')
|
|
484
|
+
|
|
485
|
+
// Request not executed yet
|
|
486
|
+
console.log('Composable created')
|
|
487
|
+
|
|
488
|
+
// Request executes on first access to data
|
|
489
|
+
console.log(api.data.value)
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
### Automatic Reactivity
|
|
493
|
+
|
|
494
|
+
When using ref or computed in parameters, requests execute automatically:
|
|
495
|
+
|
|
496
|
+
```javascript
|
|
497
|
+
const userId = ref(1)
|
|
498
|
+
const { data } = useApiRef(computed(() => `/api/users/${userId.value}`))
|
|
499
|
+
|
|
500
|
+
// Each userId change triggers a new request
|
|
501
|
+
userId.value = 2 // Request to /api/users/2
|
|
502
|
+
userId.value = 3 // Request to /api/users/3
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
### Preventing Duplicates
|
|
506
|
+
|
|
507
|
+
If a request is already running, a new request won't start:
|
|
508
|
+
|
|
509
|
+
```javascript
|
|
510
|
+
const { reset, loading } = useApiRef('/api/users')
|
|
511
|
+
|
|
512
|
+
await reset() // First request
|
|
513
|
+
// loading.value === true
|
|
514
|
+
|
|
515
|
+
await reset() // This call will be ignored until the first completes
|
|
516
|
+
```
|
|
517
|
+
|