In my react application I have a few parameters that the user comes to the application that provide some information about where they came from. Is there a way using react-router to preserve these query params throughout the entire application. meaning every time a route is changed Id like those query params to stay in the url. The only examples I've seen are passing query params between routes but not keeping them around for every route.
We can define and use a useQuery Hook in a component to get query parameters. To pass in query parameters, we just add them to the Link s to props as usual. For example, we can write the following: We first defined the useQuery Hook to get the query parameters of the URL via the URLSearchParams constructor.
To protect routes, the private components must also have access to the isLoggedIn value. You can do this by creating a new component that accepts the isLoggedIn state as a prop and the private component as a child. For instance, if your new component is named "Protected", you would render a private component like this.
React Router is a standard library for routing in React. It enables the navigation among views of various components in a React Application, allows changing the browser URL, and keeps the UI in sync with the URL. Let us create a simple application to React to understand how the React Router works.
Get a single Query String value import React from 'react'; import { useSearchParams } from 'react-router-dom'; const Users = () => { const [searchParams] = useSearchParams(); console. log(searchParams); // ▶ URLSearchParams {} return <div>Users</div>; };
UPDATE
Solution for react-router v4 is available.
Solution for react-router v3:
I wrote this little history v3 (it's compatible with react-router v3) enhancer in Typescript. It will preserve given set of query parameters. Be careful - history passed to this function has to be enhanced with useQueries.
import {History, Location, LocationDescriptor} from 'history'
export default function preserveQueryHistory(history: History, queryParameters: string[]): History {
function preserveQueryParameters(path: LocationDescriptor): Location {
const location = history.createLocation(path)
const currentQuery = history.getCurrentLocation().query
for (let p of queryParameters) {
const v = (currentQuery as any)[p]
if (v) {
location.query[p] = v
}
}
return location
}
return {
...history,
push(path: LocationDescriptor) {
history.push(preserveQueryParameters(path))
},
replace(path: LocationDescriptor) {
history.replace(preserveQueryParameters(path))
}
}
}
Now use it to create history:
import useQueries from 'history/lib/useQueries'
import createBrowserHistory from 'history/lib/createBrowserHistory'
import preserveQueryHistory from './preserveQueryHistory'
const history = preserveQueryHistory(useQueries(createBrowserHistory)(), ['language'])
And in react-router:
<Router history={history}>
...
</Router>
More ultimate solution with CreateHistory
enhancer function that embeds applying useQueries
enhancer and provides ability to inject custom History
enhancer:
import {CreateHistory, History, HistoryOptions, HistoryQueries, Location, LocationDescriptor} from 'history'
import useQueries from 'history/lib/useQueries'
function preserveQueryParameters(history: History, queryParameters: string[], path: LocationDescriptor): Location {
const location = history.createLocation(path)
const currentQuery = history.getCurrentLocation().query
for (let p of queryParameters) {
const v = (currentQuery as any)[p]
if (v) {
location.query[p] = v
}
}
return location
}
function enhanceHistory<H>(history: History & H, queryParameters: string[]): History & H {
return Object.assign({}, history, {
push(path: LocationDescriptor) {
history.push(preserveQueryParameters(history, queryParameters, path))
},
replace(path: LocationDescriptor) {
history.replace(preserveQueryParameters(history, queryParameters, path))
}
})
}
export function createPreserveQueryHistoryWithEnhancer<O, H, H2>(createHistory: CreateHistory<O, H>,
queryParameters: string[], enhancer: (h: History) => History & H2): CreateHistory<O, H & H2 & HistoryQueries> {
return function (options?: HistoryOptions & O): History & H & H2 & HistoryQueries {
let h = enhancer(useQueries(createHistory)(options)) as History & H & H2 & HistoryQueries
return enhanceHistory<H & H2 & HistoryQueries>(h, queryParameters)
}
}
export function createPreserveQueryHistory<O, H>(createHistory: CreateHistory<O, H>,
queryParameters: string[]): CreateHistory<O, H & HistoryQueries> {
return createPreserveQueryHistoryWithEnhancer<O, H, {}>(createHistory, queryParameters, h => h)
}
export function preserveQueryHistoryWithEnhancer<H, H2>(history: History & H, queryParameters: string[],
enhancer: (h: History) => History & H2): History & HistoryQueries & H & H2 {
return createPreserveQueryHistoryWithEnhancer(
function () {
return history
},
queryParameters, enhancer)()
}
export function preserveQueryHistory<H>(history: History & H, queryParameters: string[]): History & HistoryQueries & H {
return preserveQueryHistoryWithEnhancer<H, {}>(history, queryParameters, h => h)
}
Usage with syncHistoryWithStore react-router-redux v4 History
enhancer:
import createBrowserHistory from 'history/lib/createBrowserHistory'
import {createPreserveQueryHistoryWithEnhancer} from './preserveQueryHistory'
import {syncHistoryWithStore} from 'react-router-redux'
const store = ...
const history = createPreserveQueryHistoryWithEnhancer(createBrowserHistory, ['language'], function (h: History) {
return syncHistoryWithStore(h, store)
})()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With