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;
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;