Assume I have the following pages on my website
example.com/somepage.php?action=a
example.com/somepage.php?action=b
example.com/somepage.php?action=b&other=c
IMPORTANT NOTE: I do not have control of the URL paths, this is how they are set, and this is why they are far from ideal.
I am creating a React app, and I am trying to set routing, so here is what I started with:
function MyNav () {
return (
<Routes>
<Route path='/somepage.php?action=a' element={<Page1 />} />
<Route path='/somepage.php?action=b' element={<Page2 />} />
<Route path='/somepage.php?action=b&other=c' element={<Page3 />} />
<Route path='*' element={<Page1 />} />
</Routes>
)
}
But this did not work. After investigation, and after looking into the window.location
object, it turned out that path
in <Route/>
will be compared to location.pathname
. So, for all the pages above, the window.location
object will look as follows:
window.location
...
pathname: "/somepage.php"
search: "?action=a" // <-------- this is for Page 1, and will be different for Page 2 and Page 3
...
So, the route for Page 1, should be set as follows
<Routes>
<Route path='/somepage.php' element={<Page1 />} />
...
</Routes>
But this would create a problem, because it will be the same route for all pages, as follows:
<Routes>
<Route path='/somepage.php' element={<Page1 />} />
<Route path='/somepage.php' element={<Page2 />} />
<Route path='/somepage.php' element={<Page3 />} />
<Route path='*' element={<Page1 />} />
</Routes>
Now, to solve the problem above, I found this solution, so I modified my code a little, as follows
function MyNav () {
const getPage = (location) => {
const params = new URL(location.href).searchParams;
const action = params.get('action');
const other = params.get('other');
if (action == 'a') {
return <Page1 />
}
if (action == 'b') {
if (other == 'c') {
return <Page3 />
}
else {
return <Page2 />
}
}
}
return (
<Routes>
<Route path='/somepage.php' element={ getPage (location) } />
<Route path='*' element={<Page1 />} />
</Routes>
)
}
Now this works (yay!), however it defeats the purpose of the path
prop in <Route/>
. So, is there a way to directly search for the search parameters from within <Route/>
? Maybe something like this? (IMPORTANT: THE FOLLOWING IS PSEUDO CODE)
<Routes>
<Route path='/somepage.php' params='action=a' element={<Page1 />} />
<Route path='/somepage.php' params='action=b' element={<Page2 />} />
<Route path='/somepage.php' params='action=b&other=c' element={<Page3 />} />
<Route path='*' element={<Page1 />} />
</Routes>
RRD only concerns itself with the path part of the URL with regards to route matching. Your middle implementation is the closest to being correct. The best you can do is to render a single route that matched by the URL path, and check the queryString in a routed component. I'd suggest refactoring it into its own component that reads the queryString though and conditionally returns the correct component.
Example:
import { useSearchParams } from 'react-router-dom';
const Page = () => {
const [searchParams] = useSearchParams();
const action = searchParams.get("action");
const other = searchParams.get("other");
switch(action) {
case "a":
default:
return <Page1 />;
case "b":
switch(other) {
case "c":
return <Page3 />;
default:
return <Page2 />;
}
}
};
<Routes>
<Route path='/somepage.php' element={<Page />} />
<Route path='*' element={<Page1 />} />
</Routes>