All files / app/features/search useRouteWithSearchFilters.ts

0% Statements 0/24
0% Branches 0/6
0% Functions 0/7
0% Lines 0/24

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                                                                                                                                 
import { useRouter } from "next/router";
import { useCallback, useEffect, useRef, useState } from "react";
import SearchFilters, {
  parsedQueryToSearchFilters,
  parseSearchFiltersToQuery,
} from "utils/searchFilters";
 
/**
 * This hook manages a state with search filters and keeps the URL in sync
 */
export default function useRouteWithSearchFilters(route: string) {
  const router = useRouter();
  const [active, setActive] = useState<SearchFilters>(() =>
    parsedQueryToSearchFilters(router.query)
  );
  const pending = useRef<SearchFilters>(active);
 
  const expectedRouteWithQuery = `${route}?${parseSearchFiltersToQuery(
    active
  )}`;
  const routerQueryIsReady = router.isReady;
  useEffect(() => {
    Iif (routerQueryIsReady) {
      router.push(expectedRouteWithQuery, expectedRouteWithQuery, {
        shallow: true,
      });
    }
  }, [expectedRouteWithQuery, routerQueryIsReady]); // eslint-disable-line react-hooks/exhaustive-deps
  // router excluded from deps because instance changes. @see https://github.com/vercel/next.js/issues/18127
 
  const change = useCallback(
    <T extends keyof SearchFilters>(
      filter: T,
      value: Exclude<SearchFilters[T], undefined>
    ) => {
      pending.current = { ...pending.current, [filter]: value };
    },
    []
  );
 
  const remove = useCallback((filter: keyof SearchFilters) => {
    delete pending.current[filter];
    //need to copy the object or setState may not cause re-render
    pending.current = { ...pending.current };
  }, []);
 
  const apply = useCallback(() => {
    setActive(pending.current);
  }, []);
 
  const clear = useCallback(() => {
    pending.current = {};
  }, []);
 
  const any = !!(
    active.hostingStatusOptions?.length ||
    active.lastActive ||
    active.location ||
    active.numGuests ||
    active.query
  );
 
  return { active, change, remove, apply, clear, any };
}