Skip to content

Commit

Permalink
fix(useLocalStorage, useSessionStorage): replace hook with noop i…
Browse files Browse the repository at this point in the history
…n case of storage absence. (#540)

fix: #521
  • Loading branch information
xobotyi authored Jan 11, 2022
1 parent f51bd52 commit 790b302
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 72 deletions.
98 changes: 62 additions & 36 deletions src/useLocalStorageValue/useLocalStorageValue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,49 @@ import {
IUseStorageValueOptions,
useStorageValue,
} from '../useStorageValue/useStorageValue';
import { isBrowser } from '../util/const';

export function useLocalStorageValue<T = unknown>(
key: string,
defaultValue?: null,
options?: IUseStorageValueOptions
): IHookReturn<T, typeof defaultValue, IUseStorageValueOptions<true | undefined>>;
export function useLocalStorageValue<T = unknown>(
key: string,
defaultValue: null,
options: IUseStorageValueOptions<false>
): IHookReturn<T, typeof defaultValue, typeof options>;

export function useLocalStorageValue<T>(
key: string,
defaultValue: T,
options?: IUseStorageValueOptions
): IHookReturn<T, typeof defaultValue, IUseStorageValueOptions<true | undefined>>;
export function useLocalStorageValue<T>(
key: string,
defaultValue: T,
options: IUseStorageValueOptions<false>
): IHookReturn<T, typeof defaultValue, typeof options>;

export function useLocalStorageValue<T>(
key: string,
defaultValue?: T | null,
options?: IUseStorageValueOptions
): IHookReturn<T, typeof defaultValue, typeof options>;
import { isBrowser, noop } from '../util/const';

let IS_LOCAL_STORAGE_AVAILABLE = false;

try {
IS_LOCAL_STORAGE_AVAILABLE = isBrowser && !!window.localStorage;
} catch {
// no need to test this flag leads to noop behaviour
/* istanbul ignore next */
IS_LOCAL_STORAGE_AVAILABLE = false;
}

interface IUseLocalStorageValue {
<T = unknown>(key: string, defaultValue?: null, options?: IUseStorageValueOptions): IHookReturn<
T,
typeof defaultValue,
IUseStorageValueOptions<true | undefined>
>;

<T = unknown>(
key: string,
defaultValue: null,
options: IUseStorageValueOptions<false>
): IHookReturn<T, typeof defaultValue, typeof options>;

<T>(key: string, defaultValue: T, options?: IUseStorageValueOptions): IHookReturn<
T,
typeof defaultValue,
IUseStorageValueOptions<true | undefined>
>;

<T>(key: string, defaultValue: T, options: IUseStorageValueOptions<false>): IHookReturn<
T,
typeof defaultValue,
typeof options
>;

<T>(key: string, defaultValue?: T | null, options?: IUseStorageValueOptions): IHookReturn<
T,
typeof defaultValue,
typeof options
>;
}

/**
* Manages a single localStorage key.
Expand All @@ -40,10 +54,22 @@ export function useLocalStorageValue<T>(
* @param defaultValue Default value to yield in case the key is not in storage
* @param options
*/
export function useLocalStorageValue<T>(
key: string,
defaultValue: T | null = null,
options: IUseStorageValueOptions = {}
): IHookReturn<T, typeof defaultValue, typeof options> {
return useStorageValue(isBrowser ? localStorage : ({} as Storage), key, defaultValue, options);
}
export const useLocalStorageValue: IUseLocalStorageValue = IS_LOCAL_STORAGE_AVAILABLE
? <T>(
key: string,
defaultValue: T | null = null,
options: IUseStorageValueOptions = {}
): IHookReturn<T, typeof defaultValue, typeof options> =>
useStorageValue(isBrowser ? localStorage : ({} as Storage), key, defaultValue, options)
: <T>(
key: string,
defaultValue: T | null = null,
options: IUseStorageValueOptions = {}
): IHookReturn<T, typeof defaultValue, typeof options> => {
/* istanbul ignore next */
if (isBrowser && process.env.NODE_ENV === 'development') {
console.warn('LocalStorage is not available in this environment');
}

return [undefined, noop, noop, noop];
};
98 changes: 62 additions & 36 deletions src/useSessionStorageValue/useSessionStorageValue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,49 @@ import {
IUseStorageValueOptions,
useStorageValue,
} from '../useStorageValue/useStorageValue';
import { isBrowser } from '../util/const';

export function useSessionStorageValue<T = unknown>(
key: string,
defaultValue?: null,
options?: IUseStorageValueOptions
): IHookReturn<T, typeof defaultValue, IUseStorageValueOptions<true | undefined>>;
export function useSessionStorageValue<T = unknown>(
key: string,
defaultValue: null,
options: IUseStorageValueOptions<false>
): IHookReturn<T, typeof defaultValue, typeof options>;

export function useSessionStorageValue<T>(
key: string,
defaultValue: T,
options?: IUseStorageValueOptions
): IHookReturn<T, typeof defaultValue, IUseStorageValueOptions<true | undefined>>;
export function useSessionStorageValue<T>(
key: string,
defaultValue: T,
options: IUseStorageValueOptions<false>
): IHookReturn<T, typeof defaultValue, typeof options>;

export function useSessionStorageValue<T>(
key: string,
defaultValue?: T | null,
options?: IUseStorageValueOptions
): IHookReturn<T, typeof defaultValue, typeof options>;
import { isBrowser, noop } from '../util/const';

let IS_SESSION_STORAGE_AVAILABLE = false;

try {
IS_SESSION_STORAGE_AVAILABLE = isBrowser && !!window.sessionStorage;
} catch {
// no need to test this flag leads to noop behaviour
/* istanbul ignore next */
IS_SESSION_STORAGE_AVAILABLE = false;
}

interface IUseSessionStorageValue {
<T = unknown>(key: string, defaultValue?: null, options?: IUseStorageValueOptions): IHookReturn<
T,
typeof defaultValue,
IUseStorageValueOptions<true | undefined>
>;

<T = unknown>(
key: string,
defaultValue: null,
options: IUseStorageValueOptions<false>
): IHookReturn<T, typeof defaultValue, typeof options>;

<T>(key: string, defaultValue: T, options?: IUseStorageValueOptions): IHookReturn<
T,
typeof defaultValue,
IUseStorageValueOptions<true | undefined>
>;

<T>(key: string, defaultValue: T, options: IUseStorageValueOptions<false>): IHookReturn<
T,
typeof defaultValue,
typeof options
>;

<T>(key: string, defaultValue?: T | null, options?: IUseStorageValueOptions): IHookReturn<
T,
typeof defaultValue,
typeof options
>;
}

/**
* Manages a single sessionStorage key.
Expand All @@ -40,10 +54,22 @@ export function useSessionStorageValue<T>(
* @param defaultValue Default value to yield in case the key is not in storage
* @param options
*/
export function useSessionStorageValue<T>(
key: string,
defaultValue: T | null = null,
options: IUseStorageValueOptions = {}
): IHookReturn<T, typeof defaultValue, typeof options> {
return useStorageValue(isBrowser ? sessionStorage : ({} as Storage), key, defaultValue, options);
}
export const useSessionStorageValue: IUseSessionStorageValue = IS_SESSION_STORAGE_AVAILABLE
? <T>(
key: string,
defaultValue: T | null = null,
options: IUseStorageValueOptions = {}
): IHookReturn<T, typeof defaultValue, typeof options> =>
useStorageValue(isBrowser ? sessionStorage : ({} as Storage), key, defaultValue, options)
: <T>(
key: string,
defaultValue: T | null = null,
options: IUseStorageValueOptions = {}
): IHookReturn<T, typeof defaultValue, typeof options> => {
/* istanbul ignore next */
if (isBrowser && process.env.NODE_ENV === 'development') {
console.warn('SessionStorage is not available in this environment');
}

return [undefined, noop, noop, noop];
};

0 comments on commit 790b302

Please sign in to comment.