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                      106x 3460x 3460x   3460x   3460x 1302x 54x 14x     1248x 1248x   1248x 1248x   1248x         1248x 1248x             3460x 72x 72x 72x     72x   72x   72x 72x 64x 64x 102x   64x     72x           3460x             3460x    
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 };
};