I'm trying to figure out how to use the useNavigate hook to navigate/redirect a user and update the query params, if there are any.
I've created a custom useNavigateParams hook that I've adapted from several different SO answers and it looks like this:
import { generatePath, ParamKeyValuePair, useNavigate } from 'react-router-dom';
import { getSearchParams, isObjectEmpty } from 'src/utils';
type TUseNavigateParams = {
uri: string;
params?: Record<string, unknown>;
};
export default function useNavigateParams() {
const navigate = useNavigate();
return ({ uri, params = {} }: TUseNavigateParams) => {
let path = uri;
if (!isObjectEmpty(params)) {
path += generatePath('?:queryString', {
uri,
queryString: getSearchParams(Object.entries(params) as ParamKeyValuePair[]),
});
}
console.log('decoded', decodeURIComponent(path));
navigate(path);
};
}
const getSearchParams = (params: ParamKeyValuePair[]) => {
let searchParams = '';
params.forEach((param, index) => {
const localDestructured = Object.entries(param[1]);
console.log('localDestructured', localDestructured);
searchParams += createSearchParams({
[param[0]]: JSON.stringify({ [localDestructured[0][0]]: localDestructured[0][1] }),
});
});
return createSearchParams(searchParams).toString();
};
The idea here is that I would essentially always use useNavigateParams throughout my project, instead of useNavigate.
My issue is the following. Something simple like the following would work fine:
const uri = 'myPath'
const filter = 'active'
const params = { filter: { status: filter } }
navigate({
uri,
params,
})
This would print,
myPath?filter={"status":"active"}
but doing something like,
const uri = 'myPath'
const filter = 'active'
const params = { filter: { status: filter, hello: 'world' } }
navigate({
uri,
params,
})
would not print,
myPath?filter={"status":"active", "hello":"world"}
I understand that I could add another forEach or figure out some hacky approach, but it just seems so bulky as it is and it is effectively in no way reusable/dynamic.
I'd like to be able to do pass in some sort of params, such as,
const uri = 'myPath'
const filter = 'active'
const params = { filter: { status: filter, hello: 'world' }, foo: 'bar', baz: { node: 'leaf' } }
navigate({
uri,
params,
})
and expect the output to be:
myPath?filter={"status":"active", "hello":"world"}&foo=bar&baz={"node":"leaf"}
Is there a cleaner and more dependable approach to achieve such a result?