How to Keep Query Params While Navigating Using React Router

Juan Otálora
2 min readDec 28, 2024

--

One of the biggest problems when trying to code a user-friendly navigation experience in your web application is keeping the query params in the URL while navigating.

Picture generated with Dall·e

For example:

  • You have a cross-query param, such as language.
  • You want to persist this query param throughout the entire user session.
  • But if you use React Router, the query params are lost by default on every navigation.
https://www.mywebapp.com/blog?language=es_ES

# You move to the Home page but… 😢

https://www.mywebapp.com

# The query params are gone.

However, there might be parameters in the URL that you don’t want to persist on navigation. For example:

https://www.mywebapp.com/blog?language=es_ES&postId=2

# You move to the Home page, but you only want to persist the language param.

https://www.mywebapp.com/blog?language=es_ES

Keep Search Params with React Router

The solution is simple: you can create a custom hook that wraps the useNavigate hook.

import { useNavigate, useSearchParams } from 'react-router-dom';

// Parameters to keep in the URL
const PARAMS_TO_KEEP = ['language'];

const useNavigateWithParams = () => {
const navigate = useNavigate();
const [searchParams] = useSearchParams();

const navigateWithParams = (path, options = {}) => {
// Filter the parameters we want to retain
const paramsToKeep = {};
PARAMS_TO_KEEP.forEach((param) => {
const value = searchParams.get(param);
if (value) {
paramsToKeep[param] = value;
}
});

// Build the new URL with the retained parameters
const url = new URL(path, window.location.origin);
Object.entries(paramsToKeep).forEach(([key, value]) => {
url.searchParams.set(key, value);
});

// Navigate to the new URL
navigate(`${url.pathname}${url.search}`, options);
};
return navigateWithParams;
};
export default useNavigateWithParams;

Typed Version in TypeScript

If you are using TypeScript, here’s a typed version of the hook:

import { useNavigate, useSearchParams, NavigateOptions } from 'react-router-dom';

// Parameters to keep in the URL
const PARAMS_TO_KEEP = ['language'];

const useNavigateWithParams = (): ((path: string, options?: NavigateOptions) => void) => {
const navigate = useNavigate();
const [searchParams] = useSearchParams();

const navigateWithParams = (path: string, options: NavigateOptions = {}): void => {
// Filter the parameters we want to retain
const paramsToKeep: Record<string, string> = {};
PARAMS_TO_KEEP.forEach((param) => {
const value = searchParams.get(param);
if (value) {
paramsToKeep[param] = value;
}
});

// Build the new URL with the retained parameters
const url = new URL(path, window.location.origin);
Object.entries(paramsToKeep).forEach(([key, value]) => {
url.searchParams.set(key, value);
});

// Navigate to the new URL
navigate(`${url.pathname}${url.search}`, options);
};
return navigateWithParams;
};
export default useNavigateWithParams;

I hope it was helpful. Keep coding!

--

--

Juan Otálora
Juan Otálora

Written by Juan Otálora

Product Frontend Engineer @ Inditex. I write about software, product and design for Frontend Developers, empowering them for what the world needs.

No responses yet