2

Assume I have the following pages on my website

  • Page 1: example.com/somepage.php?action=a
  • Page 2: example.com/somepage.php?action=b
  • Page 3: 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>
4
  • No. 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. Commented Jan 31, 2023 at 1:37
  • 1
    Just wondering if you only need to read the query param if useSearchParams does what you need here and is more succinct? Example: https://codesandbox.io/s/use-search-params-example-ki94mc Commented Jan 31, 2023 at 2:01
  • 1
    This isn't particularly better than what you have but it leverages the react-router API: v5.reactrouter.com/web/api/match. And at least you get access to the params from the match rather than having to do new URL(location.href).searchParams; Commented Jan 31, 2023 at 2:10
  • 1
    @nbermudezs - Thanks for the suggestion. I have not used it before. I will look into that. Commented Jan 31, 2023 at 14:04

1 Answer 1

1

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>
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.