Skip to content

Commit b18414b

Browse files
authored
Micro optimizations (#1018)
* code refactoring * update rerender * code refactoring * code refactoring * Update cache.ts * make tests more stable
1 parent 6f03890 commit b18414b

File tree

4 files changed

+40
-46
lines changed

4 files changed

+40
-46
lines changed

src/cache.ts

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,42 +2,42 @@ import { Cache as CacheType, Key, CacheListener } from './types'
22
import hash from './libs/hash'
33

44
export default class Cache implements CacheType {
5-
private __cache: Map<string, any>
6-
private __listeners: CacheListener[]
5+
private cache: Map<string, any>
6+
private subs: CacheListener[]
77

88
constructor(initialData: any = {}) {
9-
this.__cache = new Map(Object.entries(initialData))
10-
this.__listeners = []
9+
this.cache = new Map(Object.entries(initialData))
10+
this.subs = []
1111
}
1212

1313
get(key: Key): any {
1414
const [_key] = this.serializeKey(key)
15-
return this.__cache.get(_key)
15+
return this.cache.get(_key)
1616
}
1717

1818
set(key: Key, value: any): any {
1919
const [_key] = this.serializeKey(key)
20-
this.__cache.set(_key, value)
20+
this.cache.set(_key, value)
2121
this.notify()
2222
}
2323

2424
keys() {
25-
return Array.from(this.__cache.keys())
25+
return Array.from(this.cache.keys())
2626
}
2727

2828
has(key: Key) {
2929
const [_key] = this.serializeKey(key)
30-
return this.__cache.has(_key)
30+
return this.cache.has(_key)
3131
}
3232

3333
clear() {
34-
this.__cache.clear()
34+
this.cache.clear()
3535
this.notify()
3636
}
3737

3838
delete(key: Key) {
3939
const [_key] = this.serializeKey(key)
40-
this.__cache.delete(_key)
40+
this.cache.delete(_key)
4141
this.notify()
4242
}
4343

@@ -74,22 +74,22 @@ export default class Cache implements CacheType {
7474
}
7575

7676
let isSubscribed = true
77-
this.__listeners.push(listener)
77+
this.subs.push(listener)
7878

7979
return () => {
8080
if (!isSubscribed) return
8181
isSubscribed = false
82-
const index = this.__listeners.indexOf(listener)
82+
const index = this.subs.indexOf(listener)
8383
if (index > -1) {
84-
this.__listeners[index] = this.__listeners[this.__listeners.length - 1]
85-
this.__listeners.length--
84+
this.subs[index] = this.subs[this.subs.length - 1]
85+
this.subs.length--
8686
}
8787
}
8888
}
8989

9090
// Notify Cache subscribers about a change in the cache
9191
private notify() {
92-
for (let listener of this.__listeners) {
92+
for (let listener of this.subs) {
9393
listener()
9494
}
9595
}

src/use-swr-infinite.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -68,20 +68,20 @@ function useSWRInfinite<Data = any, Error = any>(
6868
// not ready
6969
}
7070

71-
const [, rerender] = useState<boolean>(false)
71+
const rerender = useState({})[1]
7272

7373
// we use cache to pass extra info (context) to fetcher so it can be globally shared
7474
// here we get the key of the fetcher context cache
7575
let contextCacheKey: string | null = null
7676
if (firstPageKey) {
77-
contextCacheKey = 'context@' + firstPageKey
77+
contextCacheKey = 'ctx@' + firstPageKey
7878
}
7979

8080
// page count is cached as well, so when navigating the list can be restored
8181
let pageCountCacheKey: string | null = null
8282
let cachedPageSize
8383
if (firstPageKey) {
84-
pageCountCacheKey = 'size@' + firstPageKey
84+
pageCountCacheKey = 'len@' + firstPageKey
8585
cachedPageSize = cache.get(pageCountCacheKey)
8686
}
8787
const pageCountRef = useRef<number>(cachedPageSize || initialSize)
@@ -105,10 +105,10 @@ function useSWRInfinite<Data = any, Error = any>(
105105

106106
// actual swr of all pages
107107
const swr = useSWR<Data[], Error>(
108-
firstPageKey ? ['many', firstPageKey] : null,
108+
firstPageKey ? ['inf', firstPageKey] : null,
109109
async () => {
110110
// get the revalidate context
111-
const { originalData, force } = cache.get(contextCacheKey) || {}
111+
const { data: originalData, force } = cache.get(contextCacheKey) || {}
112112

113113
// return an array of page data
114114
const data: Data[] = []
@@ -174,7 +174,7 @@ function useSWRInfinite<Data = any, Error = any>(
174174
if (shouldRevalidate && typeof data !== 'undefined') {
175175
// we only revalidate the pages that are changed
176176
const originalData = dataRef.current
177-
cache.set(contextCacheKey, { originalData, force: false })
177+
cache.set(contextCacheKey, { data: originalData, force: false })
178178
} else if (shouldRevalidate) {
179179
// calling `mutate()`, we revalidate all pages
180180
cache.set(contextCacheKey, { force: true })
@@ -197,7 +197,7 @@ function useSWRInfinite<Data = any, Error = any>(
197197
pageCountRef.current = arg
198198
}
199199
cache.set(pageCountCacheKey, pageCountRef.current)
200-
rerender(v => !v)
200+
rerender({})
201201
return mutate(v => v)
202202
},
203203
[mutate, pageCountCacheKey]

src/use-swr.ts

Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ function useSWR<Data = any, Error = any>(
292292
// display the data label in the React DevTools next to SWR hooks
293293
useDebugValue(stateRef.current.data)
294294

295-
const rerender = useState<unknown>(null)[1]
295+
const rerender = useState<unknown>({})[1]
296296

297297
let dispatch = useCallback(
298298
(payload: Action<Data, Error>) => {
@@ -352,26 +352,21 @@ function useSWR<Data = any, Error = any>(
352352
revalidators: Record<string, Revalidator[]>,
353353
callback: Revalidator
354354
) => {
355-
if (!callback) return
356355
if (!revalidators[key]) {
357356
revalidators[key] = [callback]
358357
} else {
359358
revalidators[key].push(callback)
360359
}
361-
}
362360

363-
const removeRevalidator = (
364-
revlidators: Record<string, Revalidator[]>,
365-
callback: Revalidator
366-
) => {
367-
if (revlidators[key]) {
368-
const revalidators = revlidators[key]
369-
const index = revalidators.indexOf(callback)
361+
return () => {
362+
const keyedRevalidators = revalidators[key]
363+
const index = keyedRevalidators.indexOf(callback)
364+
370365
if (index >= 0) {
371-
// 10x faster than splice
372-
// https://jsperf.com/array-remove-by-index
373-
revalidators[index] = revalidators[revalidators.length - 1]
374-
revalidators.pop()
366+
// O(1): faster than splice
367+
keyedRevalidators[index] =
368+
keyedRevalidators[keyedRevalidators.length - 1]
369+
keyedRevalidators.pop()
375370
}
376371
}
377372
}
@@ -573,9 +568,8 @@ function useSWR<Data = any, Error = any>(
573568
const latestKeyedData = resolveData()
574569

575570
// update the state if the key changed (not the inital render) or cache updated
576-
if (keyRef.current !== key) {
577-
keyRef.current = key
578-
}
571+
keyRef.current = key
572+
579573
if (!config.compare(currentHookData, latestKeyedData)) {
580574
dispatch({ data: latestKeyedData })
581575
}
@@ -665,9 +659,9 @@ function useSWR<Data = any, Error = any>(
665659
return false
666660
}
667661

668-
addRevalidator(FOCUS_REVALIDATORS, onFocus)
669-
addRevalidator(RECONNECT_REVALIDATORS, onReconnect)
670-
addRevalidator(CACHE_REVALIDATORS, onUpdate)
662+
const unsubFocus = addRevalidator(FOCUS_REVALIDATORS, onFocus)
663+
const unsubReconnect = addRevalidator(RECONNECT_REVALIDATORS, onReconnect)
664+
const unsubUpdate = addRevalidator(CACHE_REVALIDATORS, onUpdate)
671665

672666
return () => {
673667
// cleanup
@@ -676,9 +670,9 @@ function useSWR<Data = any, Error = any>(
676670
// mark it as unmounted
677671
unmountedRef.current = true
678672

679-
removeRevalidator(FOCUS_REVALIDATORS, onFocus)
680-
removeRevalidator(RECONNECT_REVALIDATORS, onReconnect)
681-
removeRevalidator(CACHE_REVALIDATORS, onUpdate)
673+
unsubFocus()
674+
unsubReconnect()
675+
unsubUpdate()
682676
}
683677
}, [key, revalidate])
684678

test/use-swr-configs.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { sleep } from './utils'
66
describe('useSWR - configs', () => {
77
it('should read the config fallback from the context', async () => {
88
let value = 0
9-
const INTERVAL = 10
9+
const INTERVAL = 50
1010
const fetcher = () => value++
1111

1212
function Section() {

0 commit comments

Comments
 (0)