All files / react-app/src/hooks useParams.ts

80% Statements 32/40
72.22% Branches 13/18
75% Functions 6/8
83.33% Lines 30/36

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                      80x 3387x 3387x   3387x   3387x 1247x 42x 12x     1205x 1205x   1205x 1205x   1205x         1205x 1205x             3387x 63x 63x 63x     63x   63x   63x 63x 55x 55x 94x   55x     63x           3387x             3387x    
import LZ from "lz-string";
import { useMemo } from "react";
import { useSearchParams } from "react-router";
 
import { useLocalStorage } from "./useLocalStorage";
 
/**
 * useLzQuery syncs a url query parameter with a given state.
 * LZ is a library which can compresses JSON into a uri string
 * and can decompresses JSON strings into state objects
 */
export const useLzUrl = <T>(props: { key: string; initValue?: T; redirectTab?: string }) => {
  const [params, setParams] = useSearchParams();
  const [query, setQuery] = useLocalStorage("osQuery", null);
 
  const queryString = params.get(props.key) || "";
 
  const state: T = useMemo(() => {
    if (!queryString) {
      if (query) return JSON.parse(query);
      return props.initValue;
    }
 
    const decompress = LZ.decompressFromEncodedURIComponent(queryString);
    Iif (!decompress) return props.initValue;
 
    try {
      const parsed = JSON.parse(decompress);
 
      Iif (props.redirectTab && parsed.tab !== props.redirectTab) {
        setQuery(JSON.stringify(props.initValue));
        return props.initValue;
      }
 
      setQuery(decompress);
      return parsed;
    } catch {
      return props.initValue;
    }
    // adding props.initValue causes this to loop
  }, [queryString, query, setQuery]);
 
  const onSet = (arg: (arg: T) => T | T, shouldIsolate?: boolean) => {
    const val = (() => {
      Iif (typeof arg !== "function") return arg;
      return arg(state);
    })();
 
    const compressedValue = LZ.compressToEncodedURIComponent(JSON.stringify(val));
 
    setParams(
      (s) => {
        const prevParams = (() => {
          if (shouldIsolate) return {};
          const nextVal = {} as Record<string, string>;
          for (const param of s.keys()) {
            nextVal[param] = s.get(param) || "";
          }
          return nextVal;
        })();
 
        return { ...prevParams, [props.key]: compressedValue };
      },
      { replace: true },
    );
  };
 
  const onClear = () => {
    setParams((s) => {
      s.delete(props.key);
      return s;
    });
  };
 
  return { state, queryString, onSet, onClear };
};