All files / src/store hooks.ts

37.5% Statements 12/32
0% Branches 0/4
0% Functions 0/12
31.03% Lines 9/29

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 943x           3x 3x 3x   3x                         3x           3x                                   3x                                                           3x                                
import { shallowEqual, useDispatch, useSelector, useStore } from "react-redux";
import type { TypedUseSelectorHook } from "react-redux";
import type { RootState } from "./configureStore";
import type { AppDispatch } from "./configureStore";
 
// Use throughout your app instead of plain `useDispatch` and `useSelector`
export const useAppDispatch: () => AppDispatch = useDispatch;
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
export const useAppStore = useStore<RootState>;
 
const pickObject = <T extends object, const K extends readonly (keyof T)[]>(
  value: T,
  keys: K,
): Pick<T, K[number]> => {
  const result = {} as Pick<T, K[number]>;
 
  keys.forEach((key) => {
    result[key] = value[key];
  });
 
  return result;
};
 
export const shallowEqualArray = <T>(a: readonly T[], b: readonly T[]) =>
  a.length === b.length &&
  a.every((item, index) => shallowEqual(item, b[index]));
 
type AppSelector<T> = (state: RootState) => T;
 
export const useAppSelectorPick = <
  TSelector extends (...args: never[]) => object | undefined | null,
  const K extends readonly (keyof NonNullable<ReturnType<TSelector>>)[],
>(
  selector: TSelector & AppSelector<ReturnType<TSelector>>,
  keys: K,
): Pick<NonNullable<ReturnType<TSelector>>, K[number]> | undefined => {
  return useAppSelector((state) => {
    const value = selector(state);
 
    Iif (value == null) {
      return undefined;
    }
 
    return pickObject(value, keys);
  }, shallowEqual);
};
 
export const useAppSelectorPickArray = <
  TSelector extends (...args: never[]) => readonly object[],
  const K extends readonly (keyof ReturnType<TSelector>[number])[],
>(
  selector: TSelector & AppSelector<ReturnType<TSelector>>,
  keys: K,
): Pick<ReturnType<TSelector>[number], K[number]>[] => {
  return useAppSelector(
    (state) =>
      selector(state).map((value: ReturnType<TSelector>[number]) =>
        pickObject(value, keys),
      ),
    shallowEqualArray,
  );
};
 
export function useAppSelectorMapArray<
  TSelector extends (...args: never[]) => readonly object[],
  const K extends keyof ReturnType<TSelector>[number],
>(
  selector: TSelector & AppSelector<ReturnType<TSelector>>,
  key: K,
): ReturnType<TSelector>[number][K][];
export function useAppSelectorMapArray<
  TSelector extends (...args: never[]) => readonly unknown[],
  TResult,
>(
  selector: TSelector & AppSelector<ReturnType<TSelector>>,
  mapper: (value: ReturnType<TSelector>[number]) => TResult,
): TResult[];
export function useAppSelectorMapArray(
  selector: AppSelector<readonly unknown[]>,
  keyOrMapper: PropertyKey | ((value: unknown) => unknown),
): unknown[] {
  return useAppSelector((state) => {
    const values = selector(state);
 
    Iif (typeof keyOrMapper === "function") {
      return values.map(keyOrMapper);
    }
 
    return values.map(
      (value) => (value as Record<PropertyKey, unknown>)[keyOrMapper],
    );
  }, shallowEqualArray);
}