import isEqual from 'lodash/isEqual'; import isNil from 'lodash/isNil'; import { IRequestState, ISkipQueryFn } from './RxRequestStore'; export type PartialKey = Omit & { [key in Key]?: Obj[Key] }; export type VarsCondition = (vars: Vars) => boolean; /** * Skips the request if the provided condition function returns true. * If that happens, sets the store state to the provided value. * * If you would like for the resulting data to depend on the variables, * just provide the generic skipQuery callback and do not use this function. * * @param condition - function of variables which should return true when the request should be skipped * @param value - value to be used when request is skipped */ export function skipIf( condition: VarsCondition, value: Data ): ISkipQueryFn { return (vars: Vars) => { if (condition(vars)) return value; return undefined; }; } /** * Skips the request if variables are exactly null. * Sets the store state to the provided value * * @param value - value to hold as the result of the request which never happened */ export function skipIfNull( value: Data | null = null ): ISkipQueryFn { return (vars: Vars) => { if (isNil(vars)) return value; return undefined; }; } export interface CheckRequestResult { /** Should call loadData to request new data */ request: boolean; /** Should render spinner */ spinner: boolean; /** Should render error */ error: boolean; /** Should render data */ component: boolean; } export type CheckRequestStateFn = ( state: IRequestState, variables: Vars | undefined ) => CheckRequestResult; /** * Checks request store state in order to determine what to do * * @param state - request store state * @param variables - target variables * @returns object with the following boolean fields: * - request - should call loadData to request new data * - spinner - should render spinner * - error - should render error * - component - should render data */ export function checkRequestState( state: IRequestState, variables: Vars ): CheckRequestResult { const result = { request: false, spinner: false, error: false, component: false }; if (!state) return result; if (!isEqual(state.variables, variables)) { result.request = true; result.spinner = true; } else if (state.loading) { result.spinner = true; } else if (state.error) { result.error = true; } else if (state.loaded) { result.component = true; } else { result.spinner = true; result.request = true; } return result; }