Search code examples
javascriptreactjsreact-routerreact-router-dom

How extract id from react router with useparams


this is my code why it shows id undefined? i want in the sale component access to both title & id of each book but id is undefined.how can i show the value of id in the Sale component? thank you for your help! App.js

  <Route path="books" element={<Dashboard />} />
  <Route path="books/:booktitle" element={<BookDetails />} />
  <Route path="books/:booktitle/sale/:id" element={<SaleStore />} />

Dashbaord:

 {books.map((book) => (
                  <div className="col" key={book.id}>
                    <div className="card h-100" >
                      <div className="card-img-top pb-5 mb-5">
                      </div>
                      <div className="card-body">
                        <Link to={`/books/${encodeURIComponent(book.title)}`}>
                          <button type="submit" className="btn custome-btn purple-active-ghost w-100">
                            {book.title}
                          </button>
                        </Link>
// rest of code

Detail:

  const { booktitle, id } = useParams();
  console.log("book Title:", booktitle);
  console.log("book Id:", id);
                     <Link to={`/books/${encodeURIComponent(booktitle)}/sale/${id}`}>
                          <button type="submit" className="btn custome-btn purple-active-ghost w-100">
                              go to sale
                          </button>
                        </Link>

Sale:

  const { booktitle, id } = useParams();
  console.log("book Title:", booktitle);
  console.log("book Id:",id);
  
        <p>{booktitle}</p> // 
      <p>{id}</p> // undefiend

Solution

  • It would appear that the BookDetails component has the undefined id param and passes it through to the link used to navigate to the sales page.

    <Route
      path="books/:booktitle" // <-- no id param!
      element={<BookDetails />}
    />
    
    const { booktitle, id } = useParams();
    console.log("book Title:", booktitle);
    console.log("book Id:", id); // <-- undefined
    
    ...
    
    <Link
      to={`/books/${encodeURIComponent(booktitle)}/sale/${id}`} // <-- undefined id!
    >
      ...
    </Link>
    

    I'd suggest a routing pattern where the book id is used earlier in the route path.

    Exmaple:

    <Route path="books">
      <Route index element={<Dashboard />} />         // "/books"
      <Route path=":title/:id">
        <Route index element={<BookDetails />} />.    // "/books/:title/:id"
        <Route path="sale" element={<SaleStore />} /> // "/books/:title/:id/sale"
      </Route>
    </Route>
    

    Update the dashboard to link to a detail page with title and id.

    {books.map((book) => (
      <div className="col" key={book.id}>
        <div className="card h-100" >
          <div className="card-img-top pb-5 mb-5">
        </div>
        <div className="card-body">
          <Link to={`${book.title}/${book.id}`}> // "/books/:title/:id"
            <button type="submit" className="btn custome-btn purple-active-ghost w-100">
              {book.title}
            </button>
          </Link>
        </div>
      </div>
    )}
    

    Now both title and id will be defined int he details component. Link to the sales page.

    const { title, id } = useParams();
    console.log("book Title:", title);
    console.log("book Id:", id);
    
    ...
    
    <Link to="sale"> // "/books/:title/:id/sale"
      <button type="submit" className="btn custome-btn purple-active-ghost w-100">
        go to sale
      </button>
    </Link>
    

    Now the book title and id should also be available in the sale component.