Skip to content

Commit

Permalink
improvement: optional location
Browse files Browse the repository at this point in the history
When using the browser location, the global window.location is similar
to the location provided by react router for instance. When you need to
use useLocation only to get query params from the current URL, that
makes the code longer and harder to maintain.

Made location optional and default to global window.location.
  • Loading branch information
Gido Manders committed Jun 14, 2024
1 parent 09a0714 commit fb09692
Show file tree
Hide file tree
Showing 6 changed files with 203 additions and 109 deletions.
28 changes: 18 additions & 10 deletions src/queryparams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,18 @@ import { parse, ParsedQuery } from 'query-string';
*/
export function queryParamsFromLocation<
QueryParams extends Record<string, unknown>
>(
location: { search?: string },
defaultQueryParams: QueryParams,
debugName: string
): QueryParams {
const currentQueryParams = location.search
? queryParamsFromSearch(location.search)
: {};
>({
location,
defaultQueryParams,
debugName
}: {
location?: { search?: string };
defaultQueryParams: QueryParams;
debugName: string;
}): QueryParams {
const currentQueryParams = queryParamsFromSearch(
location ? location.search : window.location.search
);
const mergedQueryParams = { ...defaultQueryParams, ...currentQueryParams };
return convertQueryParamsToConcreteType<QueryParams>(
mergedQueryParams,
Expand All @@ -32,9 +36,13 @@ export function queryParamsFromLocation<
);
}

function queryParamsFromSearch(search: string): ParsedQuery {
function queryParamsFromSearch(search?: string): ParsedQuery {
if (!search) {
return {};
}

if (search[0] === '?') {
search = search.substr(1);
search = search.slice(1);
}

return parse(search);
Expand Down
24 changes: 11 additions & 13 deletions src/useQueryParams.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { useState } from 'react';
import { useEffect, useState } from 'react';
import { queryParamsFromLocation } from './queryparams';

export type Config<QueryParams> = {
location: { search?: string; key?: string };
location?: { search?: string; key?: string };
defaultQueryParams: QueryParams;
debugName?: string;
};
Expand Down Expand Up @@ -55,20 +55,18 @@ export function useQueryParams<QueryParams extends Record<string, unknown>>(
): QueryParams {
const { location, defaultQueryParams, debugName = '' } = options;
const [queryParams, setQueryParams] = useState(() => {
return queryParamsFromLocation(location, defaultQueryParams, debugName);
return queryParamsFromLocation({ location, defaultQueryParams, debugName });
});

const [search, setSearch] = useState(location.search);

if (search !== location.search) {
const params = queryParamsFromLocation(
location,
defaultQueryParams,
debugName
useEffect(() => {
setQueryParams(
queryParamsFromLocation({
location,
defaultQueryParams,
debugName
})
);
setQueryParams(params);
setSearch(location.search);
}
}, [location ? location.search : window.location.search]);

return queryParams;
}
8 changes: 4 additions & 4 deletions src/withQueryParams.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,13 @@ export const withQueryParams = <
const { location, ...props } = this.props;

// @ts-expect-error accept that there might be a displayName;
const debug = WithQueryParams.displayName;
const debugName: string = WithQueryParams.displayName;

const typedQueryParams = queryParamsFromLocation(
const typedQueryParams = queryParamsFromLocation({
location,
defaultQueryParams,
debug
);
debugName
});

return <Component queryParams={typedQueryParams} {...(props as P)} />;
}
Expand Down
Loading

0 comments on commit fb09692

Please sign in to comment.