@dnb/eufemia
Version:
DNB Eufemia Design System UI Library
102 lines (101 loc) • 3.12 kB
JavaScript
"use client";
import _JSON$parse from "core-js-pure/stable/json/parse.js";
import { useCallback, useRef } from 'react';
import { useFilter } from "./useFilter.js";
import { useSharedState } from "../../../shared/helpers/useSharedState.js";
import { useIsomorphicLayoutEffect as useLayoutEffect } from "../../../shared/helpers/useIsomorphicLayoutEffect.js";
import { sanitizeUrlFilters } from "../utils/sanitizeUrlFilters.js";
const emptyState = {
search: '',
filters: {}
};
export default function useFilterNextRouter(id, {
useRouter,
usePathname,
useSearchParams,
excludeSearch = false
}) {
const searchParam = `${id}-search`;
const filtersParam = `${id}-filters`;
const {
extend
} = useSharedState(id, emptyState);
const {
filters,
search
} = useFilter(id);
const router = useRouter();
const pathname = usePathname();
const searchParams = useSearchParams();
const isRestoringRef = useRef(false);
const writeToUrl = useCallback((currentSearch, currentFilters) => {
if (isRestoringRef.current) {
return;
}
const params = new URLSearchParams(searchParams.toString());
if (!excludeSearch) {
if (currentSearch) {
params.set(searchParam, currentSearch);
} else {
params.delete(searchParam);
}
}
const filterKeys = Object.keys(currentFilters);
if (filterKeys.length > 0) {
params.set(filtersParam, JSON.stringify(currentFilters));
} else {
params.delete(filtersParam);
}
router.replace(`${pathname}?${params.toString()}`);
}, [searchParam, filtersParam, searchParams, pathname, router, excludeSearch]);
const readFromUrl = useCallback(() => {
var _searchParams$get;
const urlSearch = excludeSearch ? '' : (_searchParams$get = searchParams.get(searchParam)) !== null && _searchParams$get !== void 0 ? _searchParams$get : '';
let urlFilters = {};
const filtersRaw = searchParams.get(filtersParam);
if (filtersRaw) {
try {
urlFilters = sanitizeUrlFilters(_JSON$parse(filtersRaw));
} catch {}
}
return {
search: urlSearch,
filters: urlFilters
};
}, [searchParams, searchParam, filtersParam, excludeSearch]);
useLayoutEffect(() => {
const {
search: urlSearch,
filters: urlFilters
} = readFromUrl();
const hasState = urlSearch || Object.keys(urlFilters).length > 0;
if (hasState) {
isRestoringRef.current = true;
extend({
search: urlSearch,
filters: urlFilters
});
isRestoringRef.current = false;
}
}, [readFromUrl, extend]);
const prevRef = useRef({
search: '',
filters: {}
});
useLayoutEffect(() => {
const prev = prevRef.current;
const filtersChanged = JSON.stringify(prev.filters) !== JSON.stringify(filters);
const searchChanged = prev.search !== search;
if (filtersChanged || searchChanged) {
prevRef.current = {
search,
filters
};
writeToUrl(search, filters);
}
}, [search, filters, writeToUrl]);
return {
readFromUrl
};
}
//# sourceMappingURL=useNextRouter.js.map