parent
a9461f760d
commit
67fbb401ac
@ -0,0 +1,133 @@
|
||||
import { NextRouter, useRouter } from 'next/router';
|
||||
import { ParsedUrlQuery } from 'querystring';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
type UseQueryParamReturnedFunction = (
|
||||
query: ParsedUrlQuery,
|
||||
routerAction?: 'push' | 'replace'
|
||||
) => void;
|
||||
|
||||
interface MergedQueryString {
|
||||
pathname: string;
|
||||
path: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a filtered object containing only key/value pairs that don't exist in the current
|
||||
* router path.
|
||||
*
|
||||
* @param router Nextjs router instance
|
||||
* @param filters Object containing key value pairs for filter items that should be cleaned
|
||||
*/
|
||||
export const filterQueryString = (
|
||||
router: NextRouter,
|
||||
filters: ParsedUrlQuery
|
||||
): ParsedUrlQuery => {
|
||||
const cleanedFilters: ParsedUrlQuery = {};
|
||||
|
||||
Object.keys(filters).forEach((key) => {
|
||||
if (!router.pathname.match(new RegExp(`${key}`))) {
|
||||
cleanedFilters[key] = filters[key];
|
||||
}
|
||||
});
|
||||
|
||||
return cleanedFilters;
|
||||
};
|
||||
|
||||
/**
|
||||
* Takes a query paramter object and returns a new pathname and path
|
||||
* with the new values appended.
|
||||
*
|
||||
* - If the value already exists, it is updated.
|
||||
* - If a key with the value of null is passed, it will be removed from
|
||||
* the current query paramters
|
||||
*
|
||||
* ## Example usage:
|
||||
*
|
||||
* If the current URL is `/foo?bar=test` and you want to add a new query parameter, you
|
||||
* can do the following:
|
||||
*
|
||||
* ```
|
||||
* const newRoute = mergeQueryString(router, { newParam: 'value' });
|
||||
* ```
|
||||
* NewRoute will become
|
||||
*
|
||||
* ```
|
||||
* {
|
||||
* pathName: '/foo?bar=test&newParam=value',
|
||||
* path: '/foo?bar=test&newParam=value'
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param router Nextjs router instance
|
||||
* @param query Key/value pair object containing query paramters
|
||||
*/
|
||||
export const mergeQueryString = (
|
||||
router: NextRouter,
|
||||
query: ParsedUrlQuery
|
||||
): MergedQueryString => {
|
||||
const cleanedQuery = filterQueryString(router, router.query);
|
||||
|
||||
const mergedQuery = Object.assign({}, cleanedQuery, query);
|
||||
|
||||
const queryArray: string[] = [];
|
||||
|
||||
Object.keys(mergedQuery).map((key) => {
|
||||
if (mergedQuery[key]) {
|
||||
queryArray.push(`${key}=${mergedQuery[key]}`);
|
||||
}
|
||||
});
|
||||
|
||||
const pathWithoutQuery = router.asPath.match(/(.*)\?.*/);
|
||||
const asPath = pathWithoutQuery ? pathWithoutQuery[1] : router.asPath;
|
||||
|
||||
const pathname = `${router.pathname}${
|
||||
queryArray.length > 0 ? `?${queryArray.join('&')}` : ''
|
||||
}`;
|
||||
const path = `${asPath}${
|
||||
queryArray.length > 0 ? `?${queryArray.join('&')}` : ''
|
||||
}`;
|
||||
|
||||
return { pathname, path };
|
||||
};
|
||||
|
||||
/**
|
||||
* useQueryParams hook is used just to provide a callback with a nextjs
|
||||
* router instance attached to it. The returned method can be called with
|
||||
* an object of key/value pairs to route the user with the new query paramters
|
||||
*/
|
||||
export const useQueryParams = (): UseQueryParamReturnedFunction => {
|
||||
const router = useRouter();
|
||||
|
||||
return useCallback(
|
||||
(query: ParsedUrlQuery, routerAction: 'push' | 'replace' = 'push') => {
|
||||
const newRoute = mergeQueryString(router, query);
|
||||
|
||||
if (newRoute.path !== router.asPath) {
|
||||
if (routerAction === 'replace') {
|
||||
router.replace(newRoute.pathname, newRoute.path);
|
||||
} else {
|
||||
router.push(newRoute.pathname, newRoute.path);
|
||||
}
|
||||
}
|
||||
},
|
||||
[router]
|
||||
);
|
||||
};
|
||||
|
||||
export const useUpdateQueryParams = (
|
||||
filter: ParsedUrlQuery
|
||||
): ((key: string, value?: string) => void) => {
|
||||
const updateQueryParams = useQueryParams();
|
||||
|
||||
return useCallback(
|
||||
(key: string, value?: string) => {
|
||||
const query = {
|
||||
...filter,
|
||||
[key]: value,
|
||||
};
|
||||
updateQueryParams(query, 'replace');
|
||||
},
|
||||
[filter, updateQueryParams]
|
||||
);
|
||||
};
|
Loading…
Reference in new issue