Skip to content

Conversation

@Tobbe
Copy link
Contributor

@Tobbe Tobbe commented Dec 26, 2023

Users are requesting more introspection possibilities for the router.
This PR adds two hooks to get the path declared in the router for a given route.
You can use useRoutePaths() to get a map of all route names to their literal routes (e.g. { editPost: '/posts/{id:Int}/edit', post: '/posts/{id:Int}' }).
Or you can use useRoutePath('editPost') to get the path of a single route by its name

Copy/paste from the docs updates:

useRoutePaths

useRoutePaths() is a React hook you can use to get a map of all routes mapped to their literal paths, as they're defined in your routes file.

Example usage:

const routePaths = useRoutePaths()

return <pre><code>{JSON.stringify(routePaths, undefined, 2)}</code></pre>

Example output:

{
  "home": "/"
  "about": "/about",
  "login": "/login",
  "signup": "/signup",
  "forgotPassword": "/forgot-password",
  "resetPassword": "/reset-password",
  "newContact": "/contacts/new",
  "editContact": "/contacts/{id:Int}/edit",
  "contact": "/contacts/{id:Int}",
  "contacts": "/contacts",
}

useRoutePath

This is a convenience hook for when you only want the path for a single route.

const aboutPath = useRoutePath('about') // returns "/about"

is the same as

const routePaths = useRoutePaths()
const aboutPath = routePaths.about // Also returns "/about"

@Tobbe Tobbe marked this pull request as draft December 26, 2023 14:30
@Tobbe Tobbe changed the title useRoutePaths [RFC]: useRoutePaths Dec 26, 2023
@Tobbe Tobbe added the release:feature This PR introduces a new feature label Dec 26, 2023
@Tobbe Tobbe added this to the next-release milestone Dec 26, 2023
@Tobbe Tobbe mentioned this pull request Dec 26, 2023
@Tobbe Tobbe marked this pull request as ready for review December 27, 2023 22:17
@Tobbe Tobbe merged commit f3e1c37 into redwoodjs:main Dec 27, 2023
@Tobbe Tobbe changed the title [RFC]: useRoutePaths useRoutePaths Dec 27, 2023
dac09 added a commit to dac09/redwood that referenced this pull request Dec 28, 2023
…p-prebuild

* 'main' of github.com:redwoodjs/redwood: (1608 commits)
  Docker: Update to work with corepack and yarn v4 (redwoodjs#9764)
  [RFC]: useRoutePaths (redwoodjs#9755)
  Adds a note about the two commands you will use with your schema to the top of the schema file (redwoodjs#8589)
  docs: Supertokens.md: Fix typo (redwoodjs#9765)
  Fix supertokens docs & integration issues (redwoodjs#9757)
  fix(apollo): Enhance error differently for Suspense Cells (redwoodjs#9640)
  SSR smoke-test: Use <Metadata /> (redwoodjs#9763)
  chore(deps): update dependency @types/qs to v6.9.11 (redwoodjs#9761)
  chore(ci): Better error handling in detectChanges.mjs (redwoodjs#9762)
  fix(path-alias): Fix aliasing of paths using ts/jsconfig (redwoodjs#9574)
  chore(deps): update dependency @types/yargs to v17.0.32 (redwoodjs#9759)
  Make it easier to find useMatch docs (redwoodjs#9756)
  chore(unit tests): Use side-effect import to fix TS errors (redwoodjs#9754)
  fix(context): Refactor context (redwoodjs#9371)
  docs: Replaced deprecated <Set private> with PrivateSet within router.md (redwoodjs#9749)
  add TS support for storybook preview tsx config extension (redwoodjs#9309)
  fix(studio): Fix windows path issues (redwoodjs#9752)
  chore(tasks): Add comparison view to nmHoisting visualisation (redwoodjs#9751)
  chore(cli): make fs modules used in the CLI consistent (redwoodjs#9746)
  ...
jtoar pushed a commit that referenced this pull request Jan 3, 2024
Make it possible to specify route param values that need to match.

If this is your route: `<Route path="/blog/{year}/{month}/{day}"
page={BlogPostPage} name="blogPost" />`
And you want to only match posts from 2001 you can now do this:

`useMatch('/blog/{year}/{month}/{day}', { routeParams: { year: '2001' }
})`

This is **finally** a solution to matching route paths. The work started
in #7469, but we were never able to come up with an api/dx that we
really liked. This PR and #9755 together however provides a solution
that we're much more happy with, and that also supports the use case
outlined in that original PR.

Here's the example from #7469 as it could be solved with the code in
this PR

```jsx
const Navbar () => {
  const { project } = useParams()
  const routePaths = useRoutePaths()

  const modes = [
    {
      name: "Info",
      route: routes.info({ project }),
      match: useMatch(routePaths.info), // using the hook together with routePaths
    },
    {
      name: "Compare",
      route: routes.compare({ project, id: "1" }),
      match: useMatch(useRoutePath('compare')), // alternative to the above
    },
    // ...
  ]

  return (
    <>
      {modes.map((x) => <Button as={Link} to={x.route} isActive={x.match} />)}
    </>
  )
}
```

And, as described at the top of this description, we can also be more
specific than in that example if needed. Like if we only wanted to match
a specific project on the "Compare" route we could do this:

```jsx
  const modes = [
    {
      name: "Info",
      route: routes.info({ project }),
      match: useMatch(routePaths.info),
    },
    {
      name: "Compare against Alpha",
      route: routes.compare({ project, id: "1" }),
      match: useMatch(useRoutePath('compare'), { routeParams: { project: 'alpha' } }),
    },
    {
      name: "Compare against Beta",
      route: routes.compare({ project, id: "1" }),
      match: useMatch(useRoutePath('compare'), { routeParams: { project: 'beta' } }),
    },
    // ...
  ]
```

Here's another example

```jsx
<Route path="/{dynamic}/{path}" page={ExamplePage} name="example" />

const exampleRoutePath = useRoutePath('example')
// => '/{dynamic}/{path}'

const matchOnlyDog = useMatch(exampleRoutePath, { routeParams: { dynamic: 'dog' }})
const matchFullyDynamic = useMatch(exampleRoutePath)
```

In the above example, if the current page url was
`https://example.org/dog/fido` then both `matchOnlyDog` and
`matchFullyDynamic` would have `match: true`.
If the current page instead was `https://example.org/cat/garfield` then
only `matchFullyDynamic` would match

(This PR replaces #9774)
@jtoar jtoar modified the milestones: next-release, v7.0.0 Jan 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release:feature This PR introduces a new feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants