I am creating a project with react-router-dom where I want the URL to hold an id. The id will be used to fetch information about the item with that id from a database and render it on the page. I've already successfully implemented data loading based on the id in the url.
My issue is that react-router-dom seems to interpret the url with the id as an unknown route and redirects it to my error page.
This is how my routes are set up:
const router = createBrowserRouter([
{
path: "/",
element: <Root />,
errorElement: <Error />,
children: [
{ path: "/", element: <Home /> },
{ path: "progress", element: <Progress /> },
{ path: "logworkout", element: <LogWorkout /> },
{
path: "programs",
element: <Programs />,
children: [
{ index: true, element: <Navigate to="myprograms" replace /> },
{ path: "discover", element: <DiscoverPrograms /> },
{
path: "myprograms",
element: <MyPrograms />,
children: [
{
path: ":programID",
element: <ProgramView />,
loader: programViewLoader,
},
],
},
],
},
{ path: "product", element: <Product /> },
{ path: "contact", element: <Contact /> },
],
},
]);
I basically want /programs/myprograms/:programID to render instead of the error page. I think I followed the tutorial on react-router-dom's documentation pretty well and I can't figure out what I'm missing.
Edit: Only <Programs/> in /programs renders an Outlet
import { Outlet } from "react-router-dom";
const Programs = () => {
return (
<div className="grid overflow-hidden" style={{gridTemplateColumns: "auto 1fr"}}>
<SideBar />
<div className="overflow-auto">
<Outlet />
</div>
</div>
);
};
export default Programs;
Edit: The issue isn't about the dynamic route but about the loader function I'm using for <ProgramView/>. Apparently, I'm not returning a value in the loader.
import Cookies from "js-cookie";
import { refreshToken } from "../../../../util/auth";
export const programViewLoader = ({ params }) => {
refreshToken()
.then((refresh) => {
return fetch("http://localhost:5000/program/load-program", {
method: "POST",
headers: {
"Content-type": "application/json",
Authorization: `Bearer ${Cookies.get("accessToken")}`,
},
body: JSON.stringify({
programID: params.programID,
}),
});
})
.then((response) => {
if (!response.ok) {
return response.json().then((data) => {
throw { error: data.error, status: response.status };
});
}
return response.json();
})
.then((data) => {
console.log(data.program);
return data.program;
})
.catch((error) => {
return { error: "An error occurred while loading the program." };
});
};
However the console.log() always prints something so I'm not sure how it isn't returning anything
ProgramsandMyPrograms) render anOutletcomponent for the nested routes to render theirelementcontent into? Can you edit to include these components for a more complete minimal reproducible example?