Skip to content

Commit

Permalink
refactor: add selector
Browse files Browse the repository at this point in the history
  • Loading branch information
promer94 committed May 9, 2022
1 parent 9996059 commit b4d659e
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 16 deletions.
45 changes: 36 additions & 9 deletions src/use-swr.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useCallback, useRef, useDebugValue } from 'react'
import { useSyncExternalStoreWithSelector } from 'use-sync-external-store/shim/with-selector.js'
import { useSyncExternalStoreWithSelector } from 'use-sync-external-store/shim/with-selector'

import { defaultConfig } from './utils/config'
import { SWRGlobalState, GlobalState } from './utils/global-state'
Expand All @@ -15,7 +15,8 @@ import {
UNDEFINED,
OBJECT,
isFunction,
createCacheHelper
createCacheHelper,
isEmptyCache
} from './utils/helper'
import ConfigProvider from './utils/config-context'
import { withArgs } from './utils/resolve-args'
Expand Down Expand Up @@ -101,13 +102,42 @@ export const useSWRHandler = <Data = any, Error = any>(

// eslint-disable-next-line react-hooks/exhaustive-deps
const getSnapshot = useCallback(getCache, [cache, key])
const fallback = isUndefined(fallbackData)
? config.fallback[key]
: fallbackData

const selector = (snapshot: any) => {
const shouldStartRequest = (() => {
if (!key) return false
if (!fetcher) return false
// If `revalidateOnMount` is set, we take the value directly.
if (!isUndefined(revalidateOnMount)) return revalidateOnMount
// If it's paused, we skip revalidation.
if (getConfig().isPaused()) return false
if (suspense) return false
return true
})()
if (!shouldStartRequest) return snapshot
if (isEmptyCache(snapshot)) {
return {
isValidating: true,
isLoading: true
}
}
return snapshot
}
const isEqual = useCallback(
(prev: any, current: any) => {
let equal = true
for (const t in stateDependencies) {
if (!compare(current[t], prev[t])) {
equal = false
if (t === 'data' && isUndefined(prev[t])) {
if (!compare(current[t], fallback)) {
equal = false
}
} else {
equal = false
}
}
}
return equal
Expand All @@ -129,23 +159,20 @@ export const useSWRHandler = <Data = any, Error = any>(
),
getSnapshot,
getSnapshot,
getSnapshot,
selector,
isEqual
)

const stateRef = useRef<State<Data, Error>>(cached)

const isInitialMount = !initialMountedRef.current
const cachedData = cached.data
const fallback = isUndefined(fallbackData)
? config.fallback[key]
: fallbackData

const data = isUndefined(cachedData) ? fallback : cachedData
const error = cached.error

// Use a ref to store previous returned data. Use the inital data as its inital value.
const laggyDataRef = useRef(data)

const isInitialMount = !initialMountedRef.current
const returnedData = keepPreviousData
? isUndefined(cachedData)
? laggyDataRef.current
Expand Down
9 changes: 3 additions & 6 deletions src/utils/helper.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
import { GlobalState, SWRGlobalState } from './global-state'
import {
Key,
Cache
} from '../types'
import { Key, Cache } from '../types'
export const noop = () => {}

// Using noop() as the undefined value as undefined can possibly be replaced
Expand All @@ -15,6 +12,7 @@ export const OBJECT = Object

export const isUndefined = (v: any): v is undefined => v === UNDEFINED
export const isFunction = (v: any): v is Function => typeof v == 'function'
export const isEmptyCache = (v: any): boolean => v === EMPTY_CACHE
export const mergeObjects = (a: any, b: any) => OBJECT.assign({}, a, b)

const STR_UNDEFINED = 'undefined'
Expand All @@ -25,7 +23,6 @@ export const isDocumentDefined = typeof document != STR_UNDEFINED
export const hasRequestAnimationFrame = () =>
isWindowDefined && typeof window['requestAnimationFrame'] != STR_UNDEFINED


const EMPTY_CACHE = {}
export const createCacheHelper = <Data = any, ExtendedInfo = {}>(
cache: Cache,
Expand All @@ -47,4 +44,4 @@ export const createCacheHelper = <Data = any, ExtendedInfo = {}>(
// Subscriber
state[5]
] as const
}
}
2 changes: 1 addition & 1 deletion test/use-swr-loading.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ describe('useSWR - loading', () => {
expect(dataLoaded).toEqual(true)
})

it('should avoid extra rerenders when the data is the same', async () => {
it('should avoid extra rerenders when the fallback is the same as cache', async () => {
let renderCount = 0,
initialDataLoaded = false,
mutationDataLoaded = false
Expand Down

0 comments on commit b4d659e

Please sign in to comment.