Mayron
Mayron

Reputation: 2394

Using Reach Router with nested routes fails to parse params

With Reach router (not React router!) I have 2 nested routes:

/g/123 /g/123/about

Where 123 is a :groupId parameter:

import React from "react";
import { Router } from "@reach/router";
import GroupPage from "../components/dynamic-pages/group";
import PostsView from "../components/group/views/posts";
import AboutView from "../components/group/views/about";

const App = () => {
  return (
    <Router>
      <GroupPage path="/g/:groupId">
        <PostsView path="/" />
        <AboutView path="/about" />
      </GroupPage>
    </Router>
  );
};

export default App;

And in the outer GroupPage component I need to use the :groupId parameter:

const GroupPage: React.FC<RouteComponentProps> = ({ children }) => {
  debugger;
  const params = useParams();
  const groupId = params.groupId as string;

  // query an API using groupId and store it in a context to be 
  // accessible to other nested components (such as AboutView and PostsView)

When I go to /g/123, which renders the PostsView, it works fine and I receive the groupId of 123 inside GroupPage, however when I go to /g/123/about the groupId is lost and params is null (still when using useParams inside GroupPage).

If I move the useParams from the GroupPage into the nested AboutView, then I can receive the params and groupId from /g/123/about but this is frustrating because I don't want to have to repeat the logic for multiple nested components and would rather have it in the outer GroupPage component (which needs the groupId to query an API for group related data and then I use a context to make it available for those nested components).

Am I doing something wrong and is there a way to achieve what I need? Thank you.

Upvotes: 2

Views: 1408

Answers (3)

MarcosSantosDev
MarcosSantosDev

Reputation: 323

Maybe this solution will help you:

import React from "react";
import { Router } from "@reach/router";
import GroupPage from "../components/dynamic-pages/group";
import PostsView from "../components/group/views/posts";
import AboutView from "../components/group/views/about";

const App = () => {
  return (
    <Router>
      <GroupPage path="g/:groupId">
        <PostsView path="/" />
      </GroupPage>

      <GroupPage path="g/:groupId/about">
        <AboutView path="/" />
      </GroupPage>
    </Router>
  );
};

export default App;

Upvotes: 0

Mayron
Mayron

Reputation: 2394

I figured out that I can use useMatch with a wildcard instead to achieve this:

const GroupPage: React.FC<RouteComponentProps> = ({ children }) => {
  debugger;
  const match = useMatch("/g/:groupId/*");
  const groupId = match?.groupId as string;

documentation: https://reach.tech/router/api/useMatch

This always returns the groupId for both the PostsView and AboutView routes.

Unless anyone knows of a better way, we can consider this question resolved :)

Upvotes: 5

Ganesh chaitanya
Ganesh chaitanya

Reputation: 658

You will not get any params for useParams() for AboutView component since the route does not have any params over there.

You can set the groupId in the context and use it in AboutView

Upvotes: 0

Related Questions