Skip to content

Commit be97edc

Browse files
committed
feat: mutateTag
1 parent f521fb7 commit be97edc

File tree

11 files changed

+371
-158
lines changed

11 files changed

+371
-158
lines changed

src/_internal/index.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,13 @@ import { INFINITE_PREFIX } from './constants'
55
export { SWRConfig, revalidateEvents, INFINITE_PREFIX }
66

77
export { initCache } from './utils/cache'
8-
export { defaultConfig, cache, mutate, compare } from './utils/config'
8+
export {
9+
defaultConfig,
10+
cache,
11+
mutate,
12+
mutateTag,
13+
compare
14+
} from './utils/config'
915
import { setupDevTools } from './utils/devtools'
1016
export * from './utils/env'
1117
export { SWRGlobalState } from './utils/global-state'

src/_internal/types.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export type GlobalState = [
66
Record<string, [any, number]>, // FETCH: [data, ts]
77
Record<string, FetcherResponse<any>>, // PRELOAD
88
ScopedMutator, // Mutator
9+
TagMutator, // TagMutator
910
(key: string, value: any, prev: any) => void, // Setter
1011
(key: string, callback: (current: any, prev: any) => void) => () => void // Subscriber
1112
]
@@ -45,6 +46,7 @@ export type BlockingData<
4546
export interface InternalConfiguration {
4647
cache: Cache
4748
mutate: ScopedMutator
49+
mutateTag: TagMutator
4850
}
4951

5052
/**
@@ -206,6 +208,10 @@ export interface PublicConfiguration<
206208
* @link https://swr.vercel.app/docs/advanced/react-native#customize-focus-and-reconnect-events
207209
*/
208210
isVisible: () => boolean
211+
/**
212+
* tags to associate with the data, you can mutate data based on these tags
213+
*/
214+
tag: string[]
209215
}
210216

211217
export type FullConfiguration<
@@ -391,6 +397,7 @@ export type State<Data = any, Error = any> = {
391397
error?: Error
392398
isValidating?: boolean
393399
isLoading?: boolean
400+
_tag?: string[]
394401
}
395402

396403
export type MutatorFn<Data = any> = (
@@ -435,6 +442,12 @@ export interface ScopedMutator {
435442
): Promise<T | undefined>
436443
}
437444

445+
export type TagMutator = <Data = any, MutationData = Data>(
446+
tag: string,
447+
data?: MutationData | Promise<MutationData> | MutatorCallback<MutationData>,
448+
opts?: boolean | MutatorOptions<Data, MutationData>
449+
) => Promise<Array<MutationData | undefined>>
450+
438451
/**
439452
* @typeParam Data - The type of the data related to the key
440453
* @typeParam MutationData - The type of the data returned by the mutator

src/_internal/utils/cache.ts

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { defaultConfigOptions } from './web-preset'
22
import { IS_SERVER } from './env'
33
import { UNDEFINED, mergeObjects, noop } from './shared'
4-
import { internalMutate } from './mutate'
4+
import { internalMutate, internalMutateTag } from './mutate'
55
import { SWRGlobalState } from './global-state'
66
import * as revalidateEvents from '../events'
77

@@ -11,7 +11,8 @@ import type {
1111
RevalidateEvent,
1212
RevalidateCallback,
1313
ProviderConfiguration,
14-
GlobalState
14+
GlobalState,
15+
TagMutator
1516
} from '../types'
1617

1718
const revalidateAllKeys = (
@@ -27,8 +28,8 @@ export const initCache = <Data = any>(
2728
provider: Cache<Data>,
2829
options?: Partial<ProviderConfiguration>
2930
):
30-
| [Cache<Data>, ScopedMutator, () => void, () => void]
31-
| [Cache<Data>, ScopedMutator]
31+
| [Cache<Data>, ScopedMutator, TagMutator, () => void, () => void]
32+
| [Cache<Data>, ScopedMutator, TagMutator]
3233
| undefined => {
3334
// The global state for a specific provider will be used to deduplicate
3435
// requests and store listeners. As well as a mutate function that is bound to
@@ -44,6 +45,7 @@ export const initCache = <Data = any>(
4445
const EVENT_REVALIDATORS = {}
4546

4647
const mutate = internalMutate.bind(UNDEFINED, provider) as ScopedMutator
48+
const mutateTag = internalMutateTag.bind(UNDEFINED, provider) as TagMutator
4749
let unmount = noop
4850

4951
const subscriptions: Record<string, ((current: any, prev: any) => void)[]> =
@@ -77,6 +79,7 @@ export const initCache = <Data = any>(
7779
{},
7880
{},
7981
mutate,
82+
mutateTag,
8083
setter,
8184
subscribe
8285
])
@@ -126,8 +129,12 @@ export const initCache = <Data = any>(
126129
// We might want to inject an extra layer on top of `provider` in the future,
127130
// such as key serialization, auto GC, etc.
128131
// For now, it's just a `Map` interface without any modifications.
129-
return [provider, mutate, initProvider, unmount]
132+
return [provider, mutate, mutateTag, initProvider, unmount]
130133
}
131134

132-
return [provider, (SWRGlobalState.get(provider) as GlobalState)[4]]
135+
return [
136+
provider,
137+
(SWRGlobalState.get(provider) as GlobalState)[4],
138+
(SWRGlobalState.get(provider) as GlobalState)[5]
139+
]
133140
}

src/_internal/utils/config-context.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,14 @@ const SWRConfig: FC<
5454
if (cacheContext) {
5555
;(extendedConfig as any).cache = cacheContext[0]
5656
;(extendedConfig as any).mutate = cacheContext[1]
57+
;(extendedConfig as any).mutateTag = cacheContext[2]
5758
}
5859

5960
// Unsubscribe events.
6061
useIsomorphicLayoutEffect(() => {
6162
if (cacheContext) {
62-
cacheContext[2] && cacheContext[2]()
63-
return cacheContext[3]
63+
cacheContext[3] && cacheContext[3]()
64+
return cacheContext[4]
6465
}
6566
}, [])
6667

src/_internal/utils/config.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ import type {
44
RevalidatorOptions,
55
Revalidator,
66
ScopedMutator,
7-
Cache
7+
Cache,
8+
TagMutator
89
} from '../types'
910

1011
import { initCache } from './cache'
@@ -42,8 +43,12 @@ const onErrorRetry = (
4243
const compare = dequal
4344

4445
// Default cache provider
45-
const [cache, mutate] = initCache(new Map()) as [Cache<any>, ScopedMutator]
46-
export { cache, mutate, compare }
46+
const [cache, mutate, mutateTag] = initCache(new Map()) as [
47+
Cache<any>,
48+
ScopedMutator,
49+
TagMutator
50+
]
51+
export { cache, mutate, mutateTag, compare }
4752

4853
// Default config
4954
export const defaultConfig: FullConfiguration = mergeObjects(
@@ -72,6 +77,7 @@ export const defaultConfig: FullConfiguration = mergeObjects(
7277
isPaused: () => false,
7378
cache,
7479
mutate,
80+
mutateTag,
7581
fallback: {}
7682
},
7783
// use web preset by default

src/_internal/utils/helper.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,11 @@ export const createCacheHelper = <Data = any, T = State<Data, any>>(
3434
INITIAL_CACHE[key] = prev
3535
}
3636

37-
state[5](key, mergeObjects(prev, info), prev || EMPTY_CACHE)
37+
state[6](key, mergeObjects(prev, info), prev || EMPTY_CACHE)
3838
}
3939
},
4040
// Subscriber
41-
state[6],
41+
state[7],
4242
// Get server cache snapshot
4343
() => {
4444
if (!isUndefined(key)) {

0 commit comments

Comments
 (0)