1

Is there a way to get URL variables inside Route's element (and not the component itself), i.e.:

<Route
    path='/book/:id'
    element={<Book data={books[getUrlVarsSomehow().id]} />}
/>

This way, I can pass a single book to Book instead of passing the whole array books and choosing the correct one inside Book, which makes much more sense from a design perspective.

I am using react-router-dom v6.3.0

2
  • Can you tell me which react-router version are you using? Commented Apr 4, 2022 at 1:52
  • [email protected] Commented Apr 4, 2022 at 1:53

3 Answers 3

1

Yes, create a wrapper component that reads the route params (via useParams hook) and applies the filtering logic and passes the appropriate prop value.

Example:

import { useParams } from 'react-router-dom';

const BookWrapper = ({ books }) => {
  const { id } = useParams();
  return <Book data={books[id]} />;
};

...

<Route
  path='/book/:id'
  element={<BookWrapper books={books} />}
/>
Sign up to request clarification or add additional context in comments.

2 Comments

This is probably the best workaround, but doesn't it still feel wrong from a design perspective? BookWrapper, as the name suggests, corresponds to a single book, and yet it takes the whole array as props
@JoeC. Not at all. You can name it whatever you like, like BooksWrapper since it takes an array of books. It's not really a work around, per se, it extends naturally from how RRDv6 routes work with wrapper components. The alternative, as you point out, is to update the Book component to consume the books array as data and push the useParams hook down into that component and do the search/filter/find/etc.
0

react-router has a hook for that, useParams

Here is an example (from the react-router docs):

https://reactrouter.com/docs/en/v6/examples/route-objects


import { useParams } from "react-router-dom";

function Course() {
  let { id } = useParams<"id">();

  return (
    <div>
      <h2>
        Welcome to the {id!.split("-").map(capitalizeString).join(" ")} course!
      </h2>

      <p>This is a great course. You're gonna love it!</p>

      <Link to="/courses">See all courses</Link>
    </div>
  );
}

Live example: https://stackblitz.com/github/remix-run/react-router/tree/main/examples/route-objects?file=src/App.tsx

Comments

0

Create yourself a wrapping component you can use where ever you might need something from the URL:

import { useParams } from 'react-router-dom'

const WithParams = <T extends Record<string, string>>(props: {
  children: (provided: T) => JSX.Element
}) => <>{props.children(useParams<T>())}</>

// usage

<Route path="/my/path/:someId">
  <WithParams<{someId: string}>>
    {({someId}) => (
      <MyComponent id={someId} />
    )}
  </WithParams>
</Route>

You could create specific versions for specific path params, or create another that uses useLocation.search and parse out URL search param queries as well.

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.