Skip to content

Commit 8a3b723

Browse files
committed
feat: improve mutate function type
1 parent c75a656 commit 8a3b723

File tree

6 files changed

+82
-54
lines changed

6 files changed

+82
-54
lines changed

core/types.ts

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
1-
import { Ref, UnwrapNestedRefs } from 'vue-demi'
21
import { Cache, HistoryOptions } from 'vue-condition-watcher/_internal'
2+
import { Ref, UnwrapNestedRefs } from 'vue-demi'
33

44
export type { HistoryOptions }
55

66
export type VoidFn = () => void
77
export type Conditions<T> = {
88
[K in keyof T]: T[K]
99
}
10+
export type FinalResult<Result, AfterFetchResult> =
11+
| Promise<AfterFetchResult extends Result ? Result : AfterFetchResult>
12+
| AfterFetchResult extends Result
13+
? Result
14+
: AfterFetchResult
1015

1116
export type OnConditionsChangeReturnValue<C> = Partial<UnwrapNestedRefs<C>>
1217

@@ -20,9 +25,9 @@ export interface OnFetchErrorContext<T = any, E = any> {
2025
data: T | null
2126
}
2227

28+
type MutateFunction<T> = (arg: (oldData: T) => any) => void
2329
type MutateData = (newData: any) => void
24-
type MutateFunction = (arg: (oldData: any) => any) => void
25-
export interface Mutate extends MutateData, MutateFunction {}
30+
export interface Mutate<T> extends MutateFunction<T>, MutateData {}
2631

2732
export interface Config<Cond = Record<string, any>, Result = unknown, AfterFetchResult = Result> {
2833
fetcher: (...args: any) => Promise<Result>
@@ -41,11 +46,7 @@ export interface Config<Cond = Record<string, any>, Result = unknown, AfterFetch
4146
conditions: Partial<Cond> & Record<string, any>,
4247
cancel: VoidFn
4348
) => Promise<Record<string, any>> | Record<string, any>
44-
afterFetch?: (
45-
data: Result
46-
) => Promise<AfterFetchResult extends Result ? Result : AfterFetchResult> | AfterFetchResult extends Result
47-
? Result
48-
: AfterFetchResult
49+
afterFetch?: (data: Result) => FinalResult<Result, AfterFetchResult>
4950
onFetchError?: (ctx: OnFetchErrorContext) => Promise<Partial<OnFetchErrorContext>> | Partial<OnFetchErrorContext>
5051
}
5152

@@ -56,7 +57,7 @@ export interface UseConditionWatcherReturn<Cond, Result> {
5657
readonly data: Readonly<Ref<Result | undefined>>
5758
readonly error: Ref<any | undefined>
5859
execute: (throwOnFailed?: boolean) => void
59-
mutate: Mutate
60+
mutate: Mutate<Result>
6061
resetConditions: (conditions?: object) => void
6162
onConditionsChange: (fn: OnConditionsChangeContext<Cond>) => void
6263
onFetchSuccess: (fn: (response: any) => void) => void

core/use-condition-watcher.ts

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,28 @@
1+
import { Conditions, Config, Mutate, UseConditionWatcherReturn } from './types'
12
import {
3+
UnwrapNestedRefs,
4+
computed,
5+
getCurrentInstance,
6+
isRef,
7+
onUnmounted,
28
reactive,
9+
readonly,
310
ref,
11+
shallowRef,
12+
unref,
413
watch,
5-
readonly,
6-
UnwrapNestedRefs,
7-
onUnmounted,
814
watchEffect,
9-
unref,
10-
isRef,
11-
shallowRef,
12-
computed,
13-
getCurrentInstance,
1415
} from 'vue-demi'
15-
import { Config, UseConditionWatcherReturn, Conditions, Mutate } from './types'
16-
import { usePromiseQueue, useHistory, useCache, createEvents } from 'vue-condition-watcher/_internal'
16+
import { containsProp, isNoData as isDataEmpty, isObject, isServer, rAF } from 'vue-condition-watcher/_internal'
17+
import { createEvents, useCache, useHistory, usePromiseQueue } from 'vue-condition-watcher/_internal'
1718
import {
18-
filterNoneValueObject,
1919
createParams,
20-
syncQuery2Conditions,
21-
isEquivalent,
2220
deepClone,
21+
filterNoneValueObject,
22+
isEquivalent,
2323
pick,
24+
syncQuery2Conditions,
2425
} from 'vue-condition-watcher/_internal'
25-
import { containsProp, isNoData as isDataEmpty, isObject, isServer, rAF } from 'vue-condition-watcher/_internal'
2626

2727
export default function useConditionWatcher<Cond extends Record<string, any>, Result, AfterFetchResult = Result>(
2828
config: Config<Cond, Result, AfterFetchResult>
@@ -209,11 +209,13 @@ export default function useConditionWatcher<Cond extends Record<string, any>, Re
209209
if (pollingTimer.value) return
210210

211211
watchEffect((onCleanup) => {
212-
if (unref(watcherConfig.pollingInterval)) {
212+
const pollingInterval = unref(watcherConfig.pollingInterval)
213+
214+
if (pollingInterval) {
213215
pollingTimer.value = (() => {
214216
let timerId = null
215217
function next() {
216-
const interval = unref(watcherConfig.pollingInterval)
218+
const interval = pollingInterval
217219
if (interval && timerId !== -1) {
218220
timerId = setTimeout(nun, interval)
219221
}
@@ -249,23 +251,23 @@ export default function useConditionWatcher<Cond extends Record<string, any>, Re
249251
* - 1.
250252
* mutate(newData)
251253
* - 2.
252-
* mutate((currentData) => {
253-
* currentData[0].name = 'runkids'
254-
* return currentData
254+
* mutate((draft) => {
255+
* draft[0].name = 'runkids'
256+
* return draft
255257
* })
256258
*/
257-
const mutate = (...args): Mutate => {
259+
const mutate = (...args): Mutate<Result> => {
258260
const arg = args[0]
259261
if (arg === undefined) {
260-
return data.value as any
262+
return data.value
261263
}
262264
if (typeof arg === 'function') {
263265
data.value = arg(deepClone(data.value))
264266
} else {
265267
data.value = arg
266268
}
267269
cache.set({ ..._conditions }, data.value)
268-
return data.value as any
270+
return data.value
269271
}
270272

271273
// - History mode base on vue-router

examples/vue3/package.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@
77
},
88
"dependencies": {
99
"element-plus": "^1.3.0-beta.1",
10-
"vue": "^3.2.26",
10+
"vue": "^3.2.45",
1111
"vue-condition-watcher": "1.4.7",
12-
"vue-router": "^4.0.10"
12+
"vue-router": "^4.1.6"
1313
},
1414
"devDependencies": {
15-
"@vitejs/plugin-vue": "^2.0.1",
16-
"@vue/compiler-sfc": "^3.2.26",
17-
"typescript": "^4.3.5",
18-
"vite": "^2.7.10"
15+
"@vitejs/plugin-vue": "^3.2.0",
16+
"@vue/compiler-sfc": "^3.2.45",
17+
"typescript": "^4.9.3",
18+
"vite": "^3.2.4"
1919
}
2020
}

examples/vue3/src/api.ts

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,39 @@
1+
export type Users = {
2+
cell: string
3+
bob: {
4+
date: string
5+
age: number
6+
}
7+
email: string
8+
gender: string
9+
id: {
10+
name: string
11+
value: string
12+
}
13+
name: {
14+
title: string
15+
first: string
16+
last: string
17+
}
18+
phone: string
19+
picture: {
20+
large: string
21+
medium: string
22+
thumbnail: string
23+
}
24+
}[]
25+
export interface Result {
26+
info: {
27+
page: number
28+
results: number
29+
seed: string
30+
version: string
31+
}
32+
results: Users
33+
}
34+
135
const users = (params: Record<string, any>) =>
2-
fetch('https://randomuser.me/api/?' + query(params), { method: 'GET' }).then((res) => res.json())
36+
fetch('https://randomuser.me/api/?' + query(params), { method: 'GET' }).then((res) => res.json() as Promise<Result>)
337

438
const photos = () => fetch('https://jsonplaceholder.typicode.com/photos', { method: 'GET' }).then((res) => res.json())
539

examples/vue3/src/views/Home.vue

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
import { ref, nextTick, inject } from 'vue'
33
import { useRouter } from 'vue-router'
44
import type { ElScrollbar } from 'element-plus'
5-
// import { useConditionWatcher } from '../../../../src/index'
6-
import { useConditionWatcher } from 'vue-condition-watcher'
7-
import api from '../api'
5+
import useConditionWatcher from '../../../../core/index'
6+
// import { useConditionWatcher } from 'vue-condition-watcher'
7+
import api, { Result, Users } from '../api'
88
99
const router = useRouter()
1010
const payload = ref('')
@@ -25,7 +25,7 @@ const {
2525
onConditionsChange,
2626
onFetchSuccess,
2727
onFetchError
28-
} = useConditionWatcher(
28+
} = useConditionWatcher<{gender: string[]; page: number}, Result, Users>(
2929
{
3030
fetcher: (params) => {
3131
payload.value = JSON.stringify(params)
@@ -45,15 +45,6 @@ const {
4545
pollingWhenOffline: true,
4646
revalidateOnFocus: true,
4747
cacheProvider: inject('cacheProvider'),
48-
// cacheProvider: function localStorageProvider() {
49-
// // example by https://swr.vercel.app/docs/advanced/cache#localstorage-based-persistent-cache
50-
// const map = new Map(JSON.parse(localStorage.getItem('app-cache') || '[]'))
51-
// window.addEventListener('beforeunload', () => {
52-
// const appCache = JSON.stringify(Array.from(map.entries()))
53-
// localStorage.setItem('app-cache', appCache)
54-
// })
55-
// return map
56-
// },
5748
history: {
5849
sync: router,
5950
},
@@ -132,7 +123,7 @@ onFetchFinally(async () => {
132123
</el-col>
133124
<el-col :span="6">
134125
<el-button type="primary" @click="execute" size="small">Refresh</el-button>
135-
<el-button type="primary" @click="resetConditions" size="small">Reset Conditions</el-button>
126+
<el-button type="primary" @click="resetConditions()" size="small">Reset Conditions</el-button>
136127
<el-button type="primary" @click="updateFirstRowData" size="small">Mutate First Row Data</el-button>
137128
</el-col>
138129
</el-row>
@@ -181,4 +172,4 @@ onFetchFinally(async () => {
181172
<div class="footer">
182173
<el-pagination background layout="prev, pager, next" :total="100" v-model:current-page="conditions.page"/>
183174
</div>
184-
</template>
175+
</template>

examples/vue3/vite.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@ export default {
55
optimizeDeps: {
66
exclude: ['vue-demi']
77
}
8-
}
8+
}

0 commit comments

Comments
 (0)