I have a problem where using react-router useParams
returns string | undefined
for some reason. Let me walk you through my code.
I have a JSON file with an array of objects.
In one component I have mapped through that array:
{coursesList.map((item, i) => (
<div key={i}>
<Link to={`/courses/${item.id}`}>
<CourseCard
duration={item.duration}
available={item.available}
image={item.image}
title={item.title}
category={item.category}
text={item.text}
/>
</Link>
</div>
))}
Clicking on single course should lead to page where there are details about that special course.
In that component I have used useParams()
.
const { itemId } = useParams();
const thisCourse = coursesList.find((item) => item.id === itemId);
thisCourse
will be used to display information from the selected course.
But when I put <h2>{thisCourse.title}</h2>
it returns error Uncaught TypeError: Cannot read properties of undefined (reading 'title')
coursesList
is imported via import coursesList from "../CoursesList.json";
In App.js
I have declared routes.
<Route path="/courses" element={<Courses />}></Route>
<Route path="/courses/:itemId" element={<SingleCourse />}></Route>
UPDATE
Single Course component code
import coursesList from "../CoursesList.json";
const SingleCourse = () => {
const { itemId } = useParams();
const thisCourse = itemId
? coursesList.find((item) => item.id === itemId)
: null;
return (
<>
<header className="header-courses small-header">
<Navbar />
<div className="second-header-text">
{thisCourse?.id ? (
<h2>{thisCourse.title}</h2>
) : (
<h2>Title not found</h2>
)}
</div>
</header>
<main>
<section>Single Card content</section>
</main>
<Footer />
</>
);
};
useParams will always return string | undefined for keys
You need to make sure that you check if it exists first.
const thisCourse = itemId? coursesList.find((item) => item.id === itemId) : null;
Also check if thisCourse exists before rendering anything from it
{thisCourse?.id?
<RenderSomething/> : <p>Not found</p>
}
If you don't get itemId at all, check your url. It should look like this: "example.com/courses/123"
UPDATE:
Turns out that item.id was a number, and it always returned undefined as it was compared with a string.
So parsing item.id as a string (item.id.toString()) or itemId as a number (+itemId) was the solution