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                      94x 3368x 3368x   3368x   3368x 1246x 42x 12x     1204x 1204x   1204x 1204x   1204x         1204x 1204x             3368x 63x 63x 63x     63x   63x   63x 63x 55x 55x 94x   55x     63x           3368x             3368x    
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]); // eslint-disable-line react-hooks/exhaustive-deps
 
  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 };
};