skip to Main Content

I have a React frontend. The code follows below. My problem is that I need to get route information outside <Routes>, in navigation menu and I can’t use useParams(). On the other hand, I tried to move <Routes> outside <NavMenu> but I get an error:

Error: [default] is not a <Route> component. All component children of <Routes> must be a <Route> or <React.Fragment>

Before React 18 I could use this.props.location.pathname.split... but even that was a workaround. Also withRouter is not available anymore in react-router-dom@6.

The code, much simplified:

index.tsx

ReactDOM.createRoot(document.getElementById('react-hook'))
    .render(
        <Provider store={store}>
            <BrowserRouter>
                <App />
            </BrowserRouter>
        </Provider>
    );

app.tsx

export default () => (
    <Layout>
        <Routes>
            <Route path='/:auxParam/site/foo/:startIndex?' Component={Extra} />
        </Routes>
    </Layout>
);

layout.tsx

export default (props: { children?: React.ReactNode }) => (
    <React.Fragment>
        <NavMenu />
        <Container tag="main">
            {props.children}
        </Container>
    </React.Fragment>
);

navmenu.tsx

class NavMenu extends React.PureComponent<NavMenuProps, { isOpen: boolean }> {
  public render() {
    const auxParam: string = ...?...; // how to get it?
    return (
      <header>
        <Navbar>
          <Container>
            <NavbarBrand tag={Link} to="/">My site (React)</NavbarBrand>
            <ul>
              <NavItem>
                <NavLink tag={Link} to={`/${aux}/site/foo`}>Extra</NavLink>
              </NavItem>
            </ul>
          </Container>
        </Navbar>
      </header>
    );
  }
}
export default NavMenu;

2

Answers


  1. Update Layout to be a layout route component, e.g. it renders an Outlet component instead of the children prop.

    Example:

    Layout.tsx

    import { Outlet } from 'react-router-dom';
    
    export default () => (
      <React.Fragment>
        <NavMenu />
        <Container tag="main">
          <Outlet />
        </Container>
      </React.Fragment>
    );
    

    App.tsx

    Render Extra on the element prop. The Component prop is only useful in Data routers.

    export default () => (
      <Routes>
        <Route element={<Layout />}>
          <Route path='/:auxParam/site/foo/:startIndex?' element={<Extra />} />
        </Route>
      </Routes>
    );
    

    NavMenu.tsx

    Convert this component to a React function component so that it can use the useParams hook.

    import { Link, useParams } from 'react-router-dom';
    ...
    
    const NavMenu () => {
      const { auxParam } = useParams();
    
      return (
        <header>
          <Navbar>
            <Container>
              <NavbarBrand tag={Link} to="/">My site (React)</NavbarBrand>
              <ul>
                <NavItem>
                  <NavLink tag={Link} to={`/${aux}/site/foo`}>
                    Extra
                  </NavLink>
                </NavItem>
              </ul>
            </Container>
          </Navbar>
        </header>
      );
    }
    
    export default NavMenu;
    
    Login or Signup to reply.
  2. I’m not sure if I understood your question but I want to share this as my answer.

    import { useLocation } from 'react-router-dom';
     
    ...
    const location = useLocation();
    console.log(location.pathname);
    ...
    

    Or I prepared another solution for you.

    import { useLocation } from 'react-router-dom';
    
    class NavMenu extends React.PureComponent<NavMenuProps, { isOpen: boolean }> {
      public render() {
        const location = useLocation();
        const auxParam = location.pathname.split('/')[1]; // Adjust this based on your route structure
    
        return (
          <header>
            <Navbar>
              <Container>
                <NavbarBrand tag={Link} to="/">My site (React)</NavbarBrand>
                <ul>
                  <NavItem>
                    <NavLink tag={Link} to={`/${auxParam}/site/foo`}>Extra</NavLink>
                  </NavItem>
                </ul>
              </Container>
            </Navbar>
          </header>
        );
      }
    }
    
    export default NavMenu;
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search