Using React (and React Router) I am creating a navigation menu inside of another navigation menu. I created exactly what I am looking for but I don't understand part of the code and I want some clarity. The code I don't understand is commented with: "why is this needed".
As an experiment, I asked chat gpt to rewrite my code and it did so with the commented code removed, but that version does not work.
The code below works because it lets me select the LINK named Topology and this renders a component named Topology. Inside the rendered component are three additional links , when each of these are clicked a corresponding component is rendered.
I attached a little video of me clicking the links and the routes changing (for some reason the video didn't capture my mouse cursor but the links I click are reflected in the URL change)
Video of render
import React from 'react';
import { Routes, Route, Link } from 'react-router-dom';
function WorkSpace({children}){
return(
<div >
<div>{children}</div>
<h1>WORKSPACE</h1>
</div>
)
}
function Topology(){
return(
<div >
<nav >
<Link to="topology" >Topology</Link>
<br/>
<Link to="packet-broker" >Packet Broker</Link>
<br/>
<Link to="slice" >Slice</Link>
</nav>
<h1>Topology</h1>
<Routes>
<Route path="topology" element={<h1>TOPOLOGY WINDOW</h1>}/>
<Route path="slice" element={<h1>SLICE WINDOW</h1>} />
<Route path="packet-broker" element={<h1>Packet Broker WINDOW</h1>} />
</Routes>
</div>
)
}
function MiniTabsRenderSpace(){
return (
<div>
<Routes>
<Route path="topology" element={<Topology />}>
<Route path="topology" element={<></>} /> // <--Why is this needed?
<Route path="slice" element={<></>} /> // <--Why is this needed?
<Route path="packet-broker" element={<></>} /> // <--Why is this needed?
</Route>
</Routes>
</div>
);
}
function Nav() {
return (
<nav>
<ul>
<Link to="/topology">Topology</Link>
<br/>
<Link to="/another-link-1">Another Link-1</Link>
<br/>
<Link to="/another-link-2">Another Link-2</Link>
</ul>
</nav>
);
}
function App() {
return (
<div>
<Nav/>
<WorkSpace>
<MiniTabsRenderSpace/>
</WorkSpace>
</div>
);
}
export default App;
Using React (and React Router) I am creating a navigation menu inside of another navigation menu. I created exactly what I am looking for but I don't understand part of the code and I want some clarity. The code I don't understand is commented with: "why is this needed".
As an experiment, I asked chat gpt to rewrite my code and it did so with the commented code removed, but that version does not work.
The code below works because it lets me select the LINK named Topology and this renders a component named Topology. Inside the rendered component are three additional links , when each of these are clicked a corresponding component is rendered.
I attached a little video of me clicking the links and the routes changing (for some reason the video didn't capture my mouse cursor but the links I click are reflected in the URL change)
Video of render
import React from 'react';
import { Routes, Route, Link } from 'react-router-dom';
function WorkSpace({children}){
return(
<div >
<div>{children}</div>
<h1>WORKSPACE</h1>
</div>
)
}
function Topology(){
return(
<div >
<nav >
<Link to="topology" >Topology</Link>
<br/>
<Link to="packet-broker" >Packet Broker</Link>
<br/>
<Link to="slice" >Slice</Link>
</nav>
<h1>Topology</h1>
<Routes>
<Route path="topology" element={<h1>TOPOLOGY WINDOW</h1>}/>
<Route path="slice" element={<h1>SLICE WINDOW</h1>} />
<Route path="packet-broker" element={<h1>Packet Broker WINDOW</h1>} />
</Routes>
</div>
)
}
function MiniTabsRenderSpace(){
return (
<div>
<Routes>
<Route path="topology" element={<Topology />}>
<Route path="topology" element={<></>} /> // <--Why is this needed?
<Route path="slice" element={<></>} /> // <--Why is this needed?
<Route path="packet-broker" element={<></>} /> // <--Why is this needed?
</Route>
</Routes>
</div>
);
}
function Nav() {
return (
<nav>
<ul>
<Link to="/topology">Topology</Link>
<br/>
<Link to="/another-link-1">Another Link-1</Link>
<br/>
<Link to="/another-link-2">Another Link-2</Link>
</ul>
</nav>
);
}
function App() {
return (
<div>
<Nav/>
<WorkSpace>
<MiniTabsRenderSpace/>
</WorkSpace>
</div>
);
}
export default App;
Share
Improve this question
asked Jan 17 at 20:54
WilliamWilliam
4,58818 gold badges66 silver badges117 bronze badges
1 Answer
Reset to default 1You need the nested "/topology"
routes because Topology
is rendered as a layout route and React-Router needs the nested routes to exist in the routing tree to have a leaf node that is "matchable". It's unclear how exactly React-Router is then able to render the appropriate routed components from the descendent routes Topology
is rendering, but I'll assume this is an internal implementation detail that just happens to work out since they all technically render on the same URL path.
That said, your implementation is incorrect.
If you wish to keep Topology
as-is rendering descendent routes
Update your routes to render
"/topology"
as a layout route, and renderTopology
as both an index route (i.e. on"/topology"
) component and on a splat route (i.e.path="*"
) component to allow descendent route matching, i.e. the children routes it renders.function MiniTabsRenderSpace() { return ( <div> <Routes> <Route path="topology"> <Route index path="*" element={<Topology />} /> </Route> </Routes> </div> ); }
Update the
Link
components to correctly navigate relative to the parent"/topology"
path by prepending them with".."
.function Topology() { return ( <div> <nav> <Link to="../topology">Topology</Link> <br /> <Link to="../packet-broker">Packet Broker</Link> <br /> <Link to="../slice">Slice</Link> </nav> <h1>Topology</h1> <Routes> <Route path="topology" element={<h1>TOPOLOGY WINDOW</h1>} /> <Route path="slice" element={<h1>SLICE WINDOW</h1>} /> <Route path="packet-broker" element={<h1>Packet Broker WINDOW</h1>} /> </Routes> </div> ); }
If you wish to use Topology
as a layout route
Update your routes to render
"/topology"
as a layout route that rendersTopology
. Render the nested routes under this parent layout route.function MiniTabsRenderSpace() { return ( <div> <Routes> <Route path="topology" element={<Topology />}> <Route path="topology" element={<h1>TOPOLOGY WINDOW</h1>} /> <Route path="slice" element={<h1>SLICE WINDOW</h1>} /> <Route path="packet-broker" element={<h1>Packet Broker WINDOW</h1>} /> </Route> </Routes> </div> ); }
Update the
Link
components to correctly navigate relative to the parent"/topology"
path by prepending them with"."
. Note that not using prepending"."
to the link target paths will still work, it's suggested to be more explicit. Render anOutlet
component in place of the routes so the nested routes have a place to render out theirelement
content to.import { Link, Outlet } from 'react-router'; function Topology() { return ( <div> <nav> <Link to="./topology">Topology</Link> <br /> <Link to="./packet-broker">Packet Broker</Link> <br /> <Link to="./slice">Slice</Link> </nav> <h1>Topology</h1> <Outlet /> </div> ); }
Important Note
In React-Router 7 you should import everything from react-router
unless you have specific platform needs, in which case you would import from react-router/<platform>
, e.g. import { RouterProvider } from 'react-router/dom';
. react-router
re-exports all from react-router-dom
, but not the other way around. react-router-dom
should be removed as a project dependency, replaced by just react-router
.
Uninstall
react-router-dom
:npm uninstall react-router-dom
Install
react-router
:npm install react-router
Update imports:
From
import { Routes, Route, Link } from 'react-router-dom';
to
import { Routes, Route, Link } from 'react-router';