Skip to content

Commit

Permalink
refactor(catalog): introduce usePathname hook, remove React Router de…
Browse files Browse the repository at this point in the history
…pendency from the Catalog
  • Loading branch information
vgeorge committed Nov 26, 2024
1 parent f31f4be commit 820730f
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 16 deletions.
7 changes: 4 additions & 3 deletions app/scripts/components/common/catalog/catalog-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { DatasetData, DatasetLayer } from "$types/veda";
import { getDatasetPath } from "$utils/routes";
import { TAXONOMY_SOURCE, TAXONOMY_TOPICS, getAllTaxonomyValues, getTaxonomy } from "$utils/veda-data/taxonomies";
import { Pill } from "$styles/pill";
import { usePathname } from "$utils/use-pathname";

interface CatalogCardProps {
dataset: DatasetData;
Expand All @@ -21,7 +22,6 @@ interface CatalogCardProps {
selectable?: boolean;
selected?: boolean;
onDatasetClick?: () => void;
pathname?: string;
linkProperties?: LinkProperties;
}

Expand Down Expand Up @@ -102,10 +102,11 @@ export const CatalogCard = (props: CatalogCardProps) => {
selectable,
selected,
onDatasetClick,
linkProperties,
pathname
linkProperties
} = props;

const pathname = usePathname();

const topics = getTaxonomy(dataset, TAXONOMY_TOPICS)?.values;
const sources = getTaxonomy(dataset, TAXONOMY_SOURCE)?.values;
const allTaxonomyValues = getAllTaxonomyValues(dataset).map((v) => v.name);
Expand Down
5 changes: 0 additions & 5 deletions app/scripts/components/common/catalog/catalog-content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ export interface CatalogContentProps {
taxonomies: Record<string, string[]>;
onAction: (action: FilterActions, value?: any) => void;
linkProperties: LinkProperties;
pathname?: string;
}

const DEFAULT_SORT_OPTION = 'asc';
Expand Down Expand Up @@ -72,7 +71,6 @@ function CatalogContent({
search,
taxonomies,
onAction,
pathname,
linkProperties
}: CatalogContentProps) {
const [exclusiveSourceSelected, setExclusiveSourceSelected] = useState<string | null>(null);
Expand Down Expand Up @@ -215,7 +213,6 @@ function CatalogContent({
exclusiveSourceSelected={exclusiveSourceSelected}
customTopOffset={isSelectable ? 50 : 0}
openByDefault={false}
pathname={pathname}
/>
<Catalog>
<CatalogTagsContainer
Expand Down Expand Up @@ -264,7 +261,6 @@ function CatalogContent({
selectable={true}
selected={selectedIds.includes(datasetLayer.id)}
onDatasetClick={() => onCardSelect(datasetLayer.id, currentDataset)}
pathname={pathname}
/>
</li>
))}
Expand All @@ -280,7 +276,6 @@ function CatalogContent({
dataset={d}
searchTerm={search}
linkProperties={linkProperties}
pathname={pathname}
/>
</li>
))}
Expand Down
5 changes: 3 additions & 2 deletions app/scripts/components/common/catalog/filters-control.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Taxonomy } from '$types/veda';
import SearchField from '$components/common/search-field';
import CheckableFilters, { OptionItem } from '$components/common/form/checkable-filter';
import { useSlidingStickyHeader, HEADER_TRANSITION_DURATION } from '$utils/use-sliding-sticky-header';
import { usePathname } from '$utils/use-pathname';

const ControlsWrapper = styled.div<{ widthValue?: string; heightValue?: string; topValue: string }>`
min-width: 20rem;
Expand All @@ -27,7 +28,6 @@ interface FiltersMenuProps {
exclusiveSourceSelected?: string | null;
customTopOffset?: number;
openByDefault?: boolean;
pathname?: string;
}

export default function FiltersControl(props: FiltersMenuProps) {
Expand All @@ -48,9 +48,10 @@ export default function FiltersControl(props: FiltersMenuProps) {
// uses as a reference (the main page header). To avoid changing the reference IDs in the
// main logic of the sliding sticky header hook, we provide this custom top offset for more control.
customTopOffset = 0,
pathname,
} = props;

const pathname = usePathname();

const controlsRef = useRef<HTMLDivElement>(null);
const [controlsHeight, setControlsHeight] = useState<number>(0);
const { isHeaderHidden, wrapperHeight } = useSlidingStickyHeader(pathname);
Expand Down
3 changes: 0 additions & 3 deletions app/scripts/components/common/catalog/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,11 @@ export interface CatalogViewProps {
onAction: () => void,
} | any;
linkProperties: LinkProperties;
pathname: string;
}

function CatalogView({
datasets,
onFilterChanges,
pathname,
linkProperties,
}: CatalogViewProps) {

Expand All @@ -72,7 +70,6 @@ function CatalogView({
search={search}
taxonomies={taxonomies}
onAction={onAction}
pathname={pathname}
linkProperties={linkProperties}
/>
</CatalogWrapper>
Expand Down
3 changes: 0 additions & 3 deletions app/scripts/components/data-catalog/container.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React from 'react';
import { useLocation } from 'react-router';
import { getString } from 'veda';
import { getAllDatasetsProps } from '$utils/veda-data';
import CatalogView from '$components/common/catalog';
Expand All @@ -20,7 +19,6 @@ import SmartLink from '$components/common/smart-link';

export default function DataCatalogContainer() {
const allDatasets = getAllDatasetsProps(veda_faux_module_datasets);
const pathname = useLocation().pathname;
const controlVars = useFiltersWithQS();

return (
Expand All @@ -37,7 +35,6 @@ export default function DataCatalogContainer() {
<CatalogView
datasets={allDatasets}
onFilterChanges={() => controlVars}
pathname={pathname}
linkProperties={{
LinkElement: SmartLink,
pathAttributeKeyName: 'to'
Expand Down
59 changes: 59 additions & 0 deletions app/scripts/utils/use-pathname.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { useEffect, useState } from 'react';

/**
* usePathname
* *
* This hook is implemented to work in both client-side rendering
* and server-side rendering environments. During SSR, it initializes the
* `pathname` as an empty string, ensuring the application remains stable in
* non-browser environments.
*
* @returns {string} The current `pathname`. Returns an empty string during SSR
* or if the `window` object is unavailable.
*/
export const usePathname = () => {
const [pathname, setPathname] = useState(
typeof window !== 'undefined' ? window.location.pathname : ''
);

useEffect(() => {
if (typeof window === 'undefined') return;

const updatePathname = () => {
setPathname(window.location.pathname);
};

// Listen to popstate events (back/forward navigation)
window.addEventListener('popstate', updatePathname);

// Detect programmatic navigation by dispatching a custom event
const originalPushState = history.pushState;
const originalReplaceState = history.replaceState;

const customEvent = new Event('pathnamechange');
const dispatchPathnameChange = () => {
window.dispatchEvent(customEvent);
};

history.pushState = function (...args) {
originalPushState.apply(this, args);
dispatchPathnameChange();
};

history.replaceState = function (...args) {
originalReplaceState.apply(this, args);
dispatchPathnameChange();
};

window.addEventListener('pathnamechange', updatePathname);

return () => {
window.removeEventListener('popstate', updatePathname);
window.removeEventListener('pathnamechange', updatePathname);
history.pushState = originalPushState;
history.replaceState = originalReplaceState;
};
}, []);

return pathname;
};

0 comments on commit 820730f

Please sign in to comment.