Search code examples
reactjsrouter

useParams returns string/undefined


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 />
    </>
  );
};

Solution

  • 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