Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

types: makes types fn and config and key more strictly #946

Merged
merged 1 commit into from
Feb 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/swr-config-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { createContext } from 'react'

import { ConfigInterface } from './types'

const SWRConfigContext = createContext<ConfigInterface>({})
const SWRConfigContext = createContext<Partial<ConfigInterface>>({})
SWRConfigContext.displayName = 'SWRConfigContext'

export default SWRConfigContext
44 changes: 21 additions & 23 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -1,50 +1,48 @@
// `null` is used for a hack to manage shared state with SWR
// https://github.com/vercel/swr/pull/918
export type fetcherFn<Data> = ((...args: any) => Data | Promise<Data>) | null
export type fetcherFn<Data> = (...args: any) => Data | Promise<Data>
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

null is only accepted for useSWR and useSWRInfinite doesn't accept null as the fetcher, so I've moved null to the argument of useSWR.

export interface ConfigInterface<
Data = any,
Error = any,
Fn extends fetcherFn<Data> = fetcherFn<Data>
> {
errorRetryInterval?: number
errorRetryInterval: number
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These values are having default values as defaultConfig, so we don't have to make the types optional.

errorRetryCount?: number
loadingTimeout?: number
focusThrottleInterval?: number
dedupingInterval?: number
refreshInterval?: number
refreshWhenHidden?: boolean
refreshWhenOffline?: boolean
revalidateOnFocus?: boolean
loadingTimeout: number
focusThrottleInterval: number
dedupingInterval: number
refreshInterval: number
refreshWhenHidden: boolean
refreshWhenOffline: boolean
revalidateOnFocus: boolean
revalidateOnMount?: boolean
revalidateOnReconnect?: boolean
shouldRetryOnError?: boolean
fetcher?: Fn
suspense?: boolean
revalidateOnReconnect: boolean
shouldRetryOnError: boolean
fetcher: Fn
suspense: boolean
initialData?: Data

isOnline?: () => boolean
isDocumentVisible?: () => boolean
isPaused?: () => boolean
onLoadingSlow?: (key: string, config: ConfigInterface<Data, Error>) => void
onSuccess?: (
isOnline: () => boolean
isDocumentVisible: () => boolean
isPaused: () => boolean
onLoadingSlow: (key: string, config: ConfigInterface<Data, Error>) => void
onSuccess: (
data: Data,
key: string,
config: ConfigInterface<Data, Error>
) => void
onError?: (
onError: (
err: Error,
key: string,
config: ConfigInterface<Data, Error>
) => void
onErrorRetry?: (
onErrorRetry: (
err: Error,
key: string,
config: ConfigInterface<Data, Error>,
revalidate: revalidateType,
revalidateOpts: RevalidateOptionInterface
) => void

compare?: (a: Data | undefined, b: Data | undefined) => boolean
compare: (a: Data | undefined, b: Data | undefined) => boolean
}

export interface RevalidateOptionInterface {
Expand Down
39 changes: 16 additions & 23 deletions src/use-swr-infinite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,39 +34,36 @@ function useSWRInfinite<Data = any, Error = any>(
): SWRInfiniteResponseInterface<Data, Error>
function useSWRInfinite<Data = any, Error = any>(
getKey: KeyLoader<Data>,
config?: SWRInfiniteConfigInterface<Data, Error>
config?: Partial<SWRInfiniteConfigInterface<Data, Error>>
): SWRInfiniteResponseInterface<Data, Error>
function useSWRInfinite<Data = any, Error = any>(
getKey: KeyLoader<Data>,
fn?: fetcherFn<Data>,
config?: SWRInfiniteConfigInterface<Data, Error>
config?: Partial<SWRInfiniteConfigInterface<Data, Error>>
): SWRInfiniteResponseInterface<Data, Error>
function useSWRInfinite<Data = any, Error = any>(
...args
getKey: KeyLoader<Data>,
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getKey is not an optional argument.

...options: any[]
): SWRInfiniteResponseInterface<Data, Error> {
let getKey: KeyLoader<Data>,
fn: fetcherFn<Data> | undefined,
config: SWRInfiniteConfigInterface<Data, Error> = {}
let _fn: fetcherFn<Data> | undefined,
_config: Partial<SWRInfiniteConfigInterface<Data, Error>> = {}

if (args.length >= 1) {
getKey = args[0]
}
if (args.length > 2) {
fn = args[1]
config = args[2]
if (options.length > 1) {
_fn = options[0]
_config = options[1]
} else {
if (typeof args[1] === 'function') {
fn = args[1]
} else if (typeof args[1] === 'object') {
config = args[1]
if (typeof options[0] === 'function') {
_fn = options[0]
} else if (typeof options[0] === 'object') {
_config = options[0]
}
}

config = Object.assign(
const config: SWRInfiniteConfigInterface<Data, Error> = Object.assign(
{},
defaultConfig,
useContext(SWRConfigContext),
config
_config
)
let {
initialSize = 1,
Expand All @@ -76,11 +73,7 @@ function useSWRInfinite<Data = any, Error = any>(
...extraConfig
} = config

if (typeof fn === 'undefined') {
// use the global fetcher
// we have to convert the type here
fn = (defaultFetcher as unknown) as fetcherFn<Data>
}
const fn = typeof _fn !== 'undefined' ? _fn : defaultFetcher

// get the serialized key of the first page
let firstPageKey: string | null = null
Expand Down
42 changes: 19 additions & 23 deletions src/use-swr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -226,30 +226,29 @@ function useSWR<Data = any, Error = any>(
): responseInterface<Data, Error>
function useSWR<Data = any, Error = any>(
key: keyInterface,
config?: ConfigInterface<Data, Error>
config?: Partial<ConfigInterface<Data, Error>>
): responseInterface<Data, Error>
function useSWR<Data = any, Error = any>(
key: keyInterface,
fn?: fetcherFn<Data>,
config?: ConfigInterface<Data, Error>
// `null` is used for a hack to manage shared state with SWR
// https://github.com/vercel/swr/pull/918
fn?: fetcherFn<Data> | null,
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

null should be accepted

config?: Partial<ConfigInterface<Data, Error>>
): responseInterface<Data, Error>
function useSWR<Data = any, Error = any>(
...args
_key: keyInterface,
...options: any[]
): responseInterface<Data, Error> {
let _key: keyInterface,
fn: fetcherFn<Data> | undefined,
config: ConfigInterface<Data, Error> = {}
if (args.length >= 1) {
_key = args[0]
}
if (args.length > 2) {
fn = args[1]
config = args[2]
let _fn: fetcherFn<Data> | undefined,
_config: Partial<ConfigInterface<Data, Error>> = {}
if (options.length > 1) {
_fn = options[0]
_config = options[1]
} else {
if (typeof args[1] === 'function') {
fn = args[1]
} else if (typeof args[1] === 'object') {
config = args[1]
if (typeof options[0] === 'function') {
_fn = options[0]
} else if (typeof options[0] === 'object') {
_config = options[0]
}
}

Expand All @@ -259,22 +258,19 @@ function useSWR<Data = any, Error = any>(
// `keyErr` is the cache key for error objects
const [key, fnArgs, keyErr, keyValidating] = cache.serializeKey(_key)

config = Object.assign(
const config: ConfigInterface<Data, Error> = Object.assign(
{},
defaultConfig,
useContext(SWRConfigContext),
config
_config
)

const configRef = useRef(config)
useIsomorphicLayoutEffect(() => {
configRef.current = config
})

if (typeof fn === 'undefined') {
// use the global fetcher
fn = config.fetcher
}
const fn = typeof _fn !== 'undefined' ? _fn : config.fetcher

const resolveData = () => {
const cachedData = cache.get(key)
Expand Down