diff --git a/src/use-swr.ts b/src/use-swr.ts index d802f416c..561f90142 100644 --- a/src/use-swr.ts +++ b/src/use-swr.ts @@ -3,7 +3,7 @@ import { defaultConfig } from './utils/config' import { SWRGlobalState, GlobalState } from './utils/global-state' import { IS_SERVER, rAF, useIsomorphicLayoutEffect } from './utils/env' import { serialize } from './utils/serialize' -import { isUndefined, UNDEFINED, mergeObjects } from './utils/helper' +import { isUndefined, UNDEFINED, OBJECT, mergeObjects } from './utils/helper' import ConfigProvider from './utils/config-context' import { useStateWithDeps } from './utils/state' import { withArgs } from './utils/resolve-args' @@ -501,7 +501,7 @@ export const useSWRHandler = ( } as SWRResponse } -export const SWRConfig = Object.defineProperty(ConfigProvider, 'default', { +export const SWRConfig = OBJECT.defineProperty(ConfigProvider, 'default', { value: defaultConfig }) as typeof ConfigProvider & { default: FullConfiguration diff --git a/src/utils/broadcast-state.ts b/src/utils/broadcast-state.ts index 2ce246c80..1d039b215 100644 --- a/src/utils/broadcast-state.ts +++ b/src/utils/broadcast-state.ts @@ -19,13 +19,11 @@ export const broadcastState: Broadcaster = ( CONCURRENT_PROMISES_TS ] = SWRGlobalState.get(cache) as GlobalState const revalidators = EVENT_REVALIDATORS[key] - const updaters = STATE_UPDATERS[key] + const updaters = STATE_UPDATERS[key] || [] // Always update states of all hooks. - if (updaters) { - for (let i = 0; i < updaters.length; ++i) { - updaters[i](data, error, isValidating) - } + for (let i = 0; i < updaters.length; ++i) { + updaters[i](data, error, isValidating) } // If we also need to revalidate, only do it for the first hook. diff --git a/src/utils/config-context.ts b/src/utils/config-context.ts index 42bb5a843..2bf2f439f 100644 --- a/src/utils/config-context.ts +++ b/src/utils/config-context.ts @@ -2,7 +2,7 @@ import { createContext, createElement, useContext, useState, FC } from 'react' import { cache as defaultCache } from './config' import { initCache } from './cache' import { mergeConfigs } from './merge-config' -import { UNDEFINED } from './helper' +import { UNDEFINED, mergeObjects } from './helper' import { useIsomorphicLayoutEffect } from './env' import { SWRConfiguration, @@ -18,7 +18,9 @@ const SWRConfig: FC<{ Partial & { provider?: (cache: Readonly) => Cache } -}> = ({ children, value }) => { +}> = props => { + const { value } = props + // Extend parent context values and middleware. const extendedConfig = mergeConfigs(useContext(SWRConfigContext), value) @@ -46,8 +48,9 @@ const SWRConfig: FC<{ return createElement( SWRConfigContext.Provider, - { value: extendedConfig }, - children + mergeObjects(props, { + value: extendedConfig + }) ) } diff --git a/src/utils/hash.ts b/src/utils/hash.ts index c8a452ccc..0c6ecaaa7 100644 --- a/src/utils/hash.ts +++ b/src/utils/hash.ts @@ -1,4 +1,4 @@ -import { isUndefined } from './helper' +import { OBJECT, isUndefined } from './helper' // use WeakMap to store the object->key mapping // so the objects can be garbage collected. @@ -25,7 +25,7 @@ export const stableHash = (arg: any): string => { let result: any let index: any - if (Object(arg) === arg && !isDate && constructor != RegExp) { + if (OBJECT(arg) === arg && !isDate && constructor != RegExp) { // Object/function, not null/date/regexp. Use WeakMap to store the id first. // If it's already hashed, directly return the result. result = table.get(arg) @@ -45,10 +45,10 @@ export const stableHash = (arg: any): string => { } table.set(arg, result) } - if (constructor == Object) { + if (constructor == OBJECT) { // Object, sort keys. result = '#' - const keys = Object.keys(arg).sort() + const keys = OBJECT.keys(arg).sort() while (!isUndefined((index = keys.pop() as string))) { if (!isUndefined(arg[index])) { result += index + ':' + stableHash(arg[index]) + ',' diff --git a/src/utils/helper.ts b/src/utils/helper.ts index a5c69ddc4..89fdf6129 100644 --- a/src/utils/helper.ts +++ b/src/utils/helper.ts @@ -6,9 +6,11 @@ export const noop = () => {} // prettier-ignore export const UNDEFINED: undefined = (/*#__NOINLINE__*/ noop()) as undefined +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 mergeObjects = (a: any, b: any) => Object.assign({}, a, b) +export const mergeObjects = (a: any, b: any) => OBJECT.assign({}, a, b) const STR_UNDEFINED = 'undefined' export const hasWindow = typeof window != STR_UNDEFINED diff --git a/src/utils/resolve-args.ts b/src/utils/resolve-args.ts index cb66343f0..916ff6cac 100644 --- a/src/utils/resolve-args.ts +++ b/src/utils/resolve-args.ts @@ -1,24 +1,17 @@ -import { useContext } from 'react' - -import { defaultConfig } from './config' -import { SWRConfigContext } from './config-context' import { mergeConfigs } from './merge-config' import { normalize } from './normalize-args' -import { mergeObjects } from './helper' +import { useSWRConfig } from './use-swr-config' // It's tricky to pass generic types as parameters, so we just directly override // the types here. export const withArgs = (hook: any) => { return (((...args: any) => { + // Get the default and inherited configuration. + const fallbackConfig = useSWRConfig() + // Normalize arguments. const [key, fn, _config] = normalize(args) - // Get the default and inherited configuration. - const fallbackConfig = mergeObjects( - defaultConfig, - useContext(SWRConfigContext) - ) - // Merge configurations. const config = mergeConfigs(fallbackConfig, _config)