13

So I'm having an error message - TypeError: Cannot read properties of undefined (reading 'params')

TypeError: Cannot read properties of undefined (reading 'params')
       5 | import products from '../products'
       6 | 
       7 | function ProductScreen({ match }) {
       8 |     const product = products.find((p) => p._id == match.params.id)
       9 |     return (
      10 |         <div>
      11 |             {product.name}

This is my ProductScreen.js file where is causing an issue

import React from 'react'
import { Link } from 'react-router-dom'
import { Row, Col, Image, ListGroup, Button, Card } from 'react-bootstrap'
import Rating from '../components/Rating'
import products from '../products'

function ProductScreen({ match }) {
    const product = products.find((p) => p._id == match.params.id)
    return (
        <div>
            {product.name}
        </div>
    )
}

export default ProductScreen

and my App.js

import { Container } from 'react-bootstrap'
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'
import Header from './components/Header'
import Footer from './components/Footer'

import HomeScreen from './screens/HomeScreen'
import ProductScreen from './screens/ProductScreen'

function App() {
  return (
    <Router>
      <Header />
      <main className="py-3">
        <Container>
          <Routes>
            <Route path='/' element={<HomeScreen/>} exact />
            <Route path='/product/:id' element={<ProductScreen/>} />
          </Routes>
        </Container>
      </main>
      <Footer />
    </Router>
  );
}

export default App;

I also tried to change match.params.id to Number or ParseInt (match.params) and still gave me an error...

I know this is very simple but I'm stuck here and cannot go further... Any help would be appreciated!

One more question - Inside App.js, where Route is, in the tutorial was using components={} attribute instead of element={}. And when I tried the same it gave me an error, so I had to fix it another way. Do you know why it caused an error?

From the tutorial

<Route path='/' component={HomeScreen} exact />

My fix --

<Route path='/' element={<HomeScreen/>} exact />

12 Answers 12

25

The tutorial appears to be older and using react-router-dom version 5 whereas you are using version 6. In version 6 there were many breaking API changes. The Route components no longer use component or render props, the element prop that is passed a valid JSX literal replaced them. route props (history, location, and match) also no longer exist, the routed components must use the React hooks to access them now.

Routes and Route

interface RouteProps {
  caseSensitive?: boolean;
  children?: React.ReactNode;
  element?: React.ReactElement | null;
  index?: boolean;
  path?: string;
}

Given route: <Route path='/product/:id' element={<ProductScreen/>} />

Use the useParams hook to access the id match param. The match param will be a string, so if your product ids are a number type, then to ensure strict equality convert the _id property to a string to use a type-safe comparison. Don't forget that Array.prototype.find returns undefined if no match is found, so the code should check the result value prior to attempting to access into it for properties when rendering.

import { Link, useParams } from 'react-router-dom';
...

function ProductScreen() {
  const { id } = useParams();
  const product = products.find((p) => String(p._id) === id);

  if (!product) return null; // or fallback UI

  return (
    <div>
      {product.name}
    </div>
  );
}
Sign up to request clarification or add additional context in comments.

2 Comments

@Reese When using Number(id) it didn't work for me. without that, it's working.
@FazleRabbiAdor Seems like your id values are strings (as they probably should be) and not of type Number. It all depends on your data properties and their types. The route params will always be a string by default though, so sometimes conversion is necessary for strict equality (===) checks.
10

I had the same problem, finally, this code worked.

import { useParams } from 'react-router-dom';

const { id } = useParams();

const product = products.find((p) => p._id === (id));

 <Route path="/product/:id" element={<ProductDetails />} />

Comments

3
import { Link, useParams } from "react-router-dom";
    ...
    
    function ProductScreen() {
      const { id } = useParams();
      const product = products.find((p) => p._id === id);
      return <div>{product.name}</div>;
    }
    
    export default ProductScreen;

1 Comment

As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.
2
import { Link, useParams } from 'react-router-dom';
...

function ProductScreen() {
  const { id } = useParams();
  const product = products.find((p) => p._id === Number(id));
  return (
    <div>
      {product.name}
    </div>
  );
}

This solved :)

Comments

2

I know this has been marked solved but I'm doing this course on Udemy as well.

Here is my working solution in case someone needs help on this course. I used params as useParams()


import React from "react";
import { Link, useParams } from "react-router-dom";
import products from "../products";

const ProductScreen = () => {
  const params = useParams();
  const product = products.find((p) => p._id === params.id);
  return <div>{product.name}</div>;
};

export default ProductScreen; 

1 Comment

Glad you answered this 12 hours before I ran into the same issue in (probably) the same course. Thank you!
2

For router 6 use this

import { Link, useParams } from 'react-router-dom';

const SingleProduct = () => {
  const { id } = useParams();
  const product = products.find(product => product._id === (id));
}

(id) without Number(id) or it will undefined

<div className='single-image'>
  <img src={product.image} alt={product.name} />
</div>

and add this in App.js

<Route path='/products/:id' element={<SingleProduct />} />

Comments

1
**In App.js file:** 

<Route path="/products/:id" element={<SingleProduct />} />

**In SingleProduct.js file:** 

import { useParams } from 'react-router-dom'

const SingleProduct = () => {

const { id } = useParams()
const product = products.find((p) => p._id === (id))

 <div>
      <img src={product.image} alt={product.name} />
      <h3>product.name</h3>
</div>
}
export default SingleProduct;


**This code worked in my case.** 

Comments

0

In the Router:

<Route path='/product/:id' element={ProductScreen} />

In the ProductScreen component:

import { useParams } from "react-router-dom";
...
const { id } = useParams();

https://v5.reactrouter.com/web/api/Hooks/useparams

Comments

0

This code might be helpful for you. In this case

function ProductScreen() {
  const[product,setProduct]=useState([]);
  const { id } = useParams();

  useEffect(()=>{
    async function fetchProduct(){
         const {data}= await axios.get('/api/products/'+id)
         setProduct(data)
     }
     fetchProduct()
 },[]);

Comments

0

You have to put

const ProductView = () => {
  const params = useParams();
  const product = products.find((p) => p._id === params.id);
}

Dont' for get to import useParams in react-router-dom!

Comments

0

I think in [email protected] vesrion it support the componant but in eairleir version react change policy and in [email protected] or more version componant is replaced by element.

But Now, You use [email protected] or highier version.

<Route path='/' element={} exact />

Comments

-1

import {useParams} from 'react-router-dom'

const { id } = useParams(); const product = products.find((p) => p._id === (id));

In app.js <Route path="/product/:id" element={} >

1 Comment

Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.