All pages are being rendered in localhost/1
, localhost/2
, localhost/3
, etc.
After the user select a card to show details, the url changes to localhost/info/:id
, this id is the id from an array.
The page with the card details let's say is localhost/info/1
, everything look good. The problem is that inside of this page there is another link to be clicked.
If this bottom is clicked, the url should change to localhost/info/1/episodes
and this new component should be rendered with the others details from the card.
How can I correctly implement this feature to render two components together? I'm still learning React Router.
All Routes.tsx
import Home from "../pages/Home";
import CharacterInfo from "../pages/CharacterInfo";
import { Route, Routes, Navigate } from "react-router-dom";
import Episodes from "../pages/Episodes";
const AllRoutes = () => {
return (
<Routes>
<Route path="/" element={<Navigate to="/1" />} />
<Route path="/info">
<Route path=":id" element={<CharacterInfo />}>
<Route path="/info/:id/episodes" element={<Episodes />} />
</Route>
</Route>
<Route path="/:p" element={<Home />} />
<Route path="*" element={<Home />} />
</Routes>
);
};
export default AllRoutes;
CharacterInfo.tsx
import { useContext, useEffect } from "react";
import { useParams, Routes, Route, Link, useNavigate } from "react-router-dom";
import { GetACharacterContext } from "../contexts/GetACharacterContext";
import Episodes from "./Episodes";
const CharacterInfo = () => {
const { characterDetail, setId } = useContext(GetACharacterContext);
const { id } = useParams();
const navigate = useNavigate();
useEffect(() => {
setId(Number(id));
}, [id]);
return (
<>
<button onClick={() => navigate("/1")}>Home</button>
<p>{characterDetail.id}</p>
<p>{characterDetail.name}</p>
<p>{characterDetail.age ? characterDetail.age : "No data"}</p>
<p>{characterDetail.occupation}</p>
<Link to={`/info/${characterDetail.id}/episodes`}>Episodes</Link>
</>
);
};
export default CharacterInfo;
Episodes.tsx
const Episodes = () => {
return <div>Episodes</div>;
};
export default Episodes;
CodePudding user response:
CharacterInfo
needs to render an Outlet
component for the nested routes it's rendering, and the path needs to be relative from the parent route.
Example:
const AllRoutes = () => {
return (
<Routes>
<Route path="/" element={<Navigate to="/1" />} />
<Route path="/info"> // "/info"
<Route path=":id" element={<CharacterInfo />}> // "/info/:id"
<Route path="episodes" element={<Episodes />} /> // "/info/:id/episodes"
</Route>
</Route>
<Route path="/:p" element={<Home />} />
<Route path="*" element={<Home />} />
</Routes>
);
};
...
const CharacterInfo = () => {
const { characterDetail, setId } = useContext(GetACharacterContext);
const { id } = useParams();
const navigate = useNavigate();
useEffect(() => {
setId(Number(id));
}, [id]);
return (
<>
<button onClick={() => navigate("/1")}>Home</button>
<p>{characterDetail.id}</p>
<p>{characterDetail.name}</p>
<p>{characterDetail.age ? characterDetail.age : "No data"}</p>
<p>{characterDetail.occupation}</p>
<Link to={`/info/${characterDetail.id}/episodes`}>Episodes</Link>
<Outlet /> // <-- nested routes render content here
</>
);
};
CodePudding user response:
You can try it like this:
<Routes>
<Route path="/" element={<Navigate to="/1" />} />
<Route path="/info/:id" element={<CharacterInfo />} />
<Route path="/info/:id/episodes" element={<Episodes />} />
</Routes>