4 min read
Advanced techniques for managing Query Parameters in React apps
Managing query parameters can be a challenging task, especially in complex reactive web applications with shareable URLs. Let's explore the approach I've developed after overcoming some initial challenges.
The problem
Managing query parameters can be a challenging task in large applications. Complexity arises when there are numerous instances where query parameters need modification, especially as the number of query parameters increases.
Handling various types of user interactions and integrating them with the app state becomes challenging, particularly in extensive and intricate reactive applications.
The case
Let’s outline the aspects that will be covered in this article:
- Reading from URL: The app should read query params on page load.
- Changing URL: URL should be changed on user’s events.
- Browser arrows: The app should react on back/forward browser buttons.
- The app should recover URL from state after you returned back from other routes.
All the examples will be given assuming developing single page React app with react-router.
The idea
The idea is as follows:
- The source of truth is always the app state, except 2 cases.
- The URL is the source of truth only in two cases:
- when the back/forward button is pressed
- when the page is loading.
- Whenever the app state changes, the URL changes accordingly.
Reading from URL
Reading from URL has 2 steps:
const readQueryParams = () => {
// 1. Converting URL from string to object
const queryParams = (qs.parse(window.location.search.slice(1)) as unknown) as AppQueryParams;
// 2. Filling app state with values
fillStoreWithValues(queryParams);
}
Changing URL
Changing URL has 2 steps:
const setQueryStringUrl = () => {
const params: AppQueryParams = {
search: search || undefined
};
// 1. Stringifying params from app state
const queryParams = qs.stringify(params);
// 2. push only in case url changed
if (
`${window.location.origin}/?${queryParams}` !==
window.location.href
) {
navigate(`?${queryParams}`);
}
return queryParams;
};
Back/forward browser buttons
Using the readQueryParams
method let’s setup back/forward buttons interactions:
// reading query params after browser back button pressed
useUpdateEffect(() => {
if (navigationType === 'POP') {
readQueryParams();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [location.key]);
Change URL when app state is changed
Using the setQueryStringUrl
method let’s setup changing URL after state is changed:
useEffect(() => {
// updating url query params after state is changed
setQueryStringUrl();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [search]);
Conclusion
To witness this approach in action, please take a look at the demo. It’s important to note that the demo provides a simple example, but this approach becomes essential when you have complex interactions between your app’s state and URL. In such scenarios, you can effectively manage URL persistence and selectively merge specific portions of your store.