【问题标题】:I cannot find the error TypeError: Cannot read properties of undefined (reading 'name')我找不到错误 TypeError: Cannot read properties of undefined (reading 'name')
【发布时间】:2021-10-30 07:41:49
【问题描述】:

我是 react 新手,当我试图从我的 react 应用程序的一个名为“products.js”的文件中的一组对象中引入一些“产品”时,我需要一些帮助。

问题是我能够在主屏幕的数组中绘制产品。但是,当我尝试在我的详细信息产品页面上绘制这些产品时(这个页面是我可以看到单个产品详细信息的页面)“ProductDetails.js”我收到错误(无论我是否尝试使用 product.name 或product.price 或其他):

TypeError: Cannot read properties of undefined (reading 'name')

为了让您了解我在说什么,我将与您分享我的代码中的一些 sn-ps,以便您了解上下文。我将从确切的错误消息开始,并以概览我的项目依赖项结束。

错误信息

TypeError: Cannot read properties of undefined (reading 'name')
ProductDetails
C:/Users/jjimennz/OneDrive/Desktop/eCommerce MERN Stack/Sprint1/frontend/src/views/ProductDetails.js:19

 16 | const ProductDetails = ({ match }) => {
  17 |   const product = products.find((p) => p._id === match.params.id);
  18 | 
> 19 |   return <div>{product.name}</div>;
  20 | };
  21 | 
  22 | export default ProductDetails;

这是我遇到麻烦的视图,不仅仅是“product.name”,我遇到任何“product.price”“product.image”...这是详细信息产品屏幕,应该在其自己的页面上向我显示每个单独的产品及其详细信息的视图,我称之为“ProductDetails.js”

import React from "react";
import products from "../products";

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

  return <div>{product.name}</div>;
};

export default ProductDetails;

这是包含我要在上述产品详细信息屏幕上绘制的产品的数组的文件。该文件名为“products.js”:

const products = [
  {
    _id: 1,
    name: "Nemeziz 19.4",
    image:
      "https://assets.adidas.com/images/w_600,f_auto,q_auto/75987ad2e31644d59d24ab3000fce766_9366/Botines_Nemeziz_19.4_Pasto_Sintetico_Verde_FV3317_41_detail.jpg",
    description: "Breve descripcion de los zapatos",
    brand: "Adidas",
    category: "Zapatos",
    price: 89.99,
    countInStock: 20,
    rating: 4.5,
    numReviews: 14,
  },
  {
    _id: 2,
    name: "Adidas Ace",
    image: "https://www.sports-ws.com/img/item/F163AD0/F163AD0654.jpg",
    description: "Breve descripcion de los zapatos",
    brand: "Adidas",
    category: "Zapatos",
    price: 149.99,
    countInStock: 8,
    rating: 4.5,
    numReviews: 15,
  },
];

export default products 

这是主屏幕的视图,我在其中显示了上述数组中的所有产品,这个效果很好,并在屏幕上绘制了数组中的每个产品。这个叫做“HomeScreen.js”

import React from "react";
import { Row, Col } from "react-bootstrap";
import Product from "../components/Product";
import products from "../products";

const HomeScreen = () => {
  return (
    <>
      <h1>Latest Products</h1>
      <Row>
        {products.map((product) => (
          <Col key={product._id} sm={12} md={6} lg={4} xl={3}>
            <Product product={product} />
          </Col>
        ))}
      </Row>
    </>
  );
};

export default HomeScreen;

这是 Product 组件,它基本上在上面的主屏幕视图的数组中绘制每个单独的产品。这个作为上面的主屏幕也很好用,它给我带来了带有名称、价格和图像的产品。我确实将此组件称为“Product.js”*

import React from "react";
import { Link } from "react-router-dom";
import { Card } from "react-bootstrap";
import Rating from "./Rating";

const Product = ({ product }) => {
  return (
    <Card className="my-3 p-3 rounded">
      <Link to={`/product/${product._id}`}>
        <Card.Img src={product.image} variant="top" />
      </Link>
      <Card.Body>
        <Link to={`/product/${product._id}`}>
          <Card.Title as="div">
            <strong>{product.name}</strong>
          </Card.Title>
        </Link>

        <Card.Text as="div">
          <Rating
            value={product.rating}
            text={`${product.numReviews} reviews`}
          />
        </Card.Text>
        <Card.Text as="h3">${product.price}</Card.Text>
      </Card.Body>
    </Card>
  );
};

export default Product; 

“App.js”文件,以便您更好地了解我的项目发生了什么

import React from "react";
import { BrowserRouter as Router, Route } from "react-router-dom";
import { Container } from "react-bootstrap";
import Header from "./components/Header";
import Footer from "./components/Footer";
import HomeScreen from "./views/HomeScreen";
import ProductDetails from "./views/ProductDetails";

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

export default App;

这是我的“package.json”文件,在我的项目中有依赖项,以防万一它有助于我解决这个问题

{
  "name": "frontend",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^5.14.1",
    "@testing-library/react": "^11.2.7",
    "@testing-library/user-event": "^12.8.3",
    "react": "^17.0.2",
    "react-bootstrap": "^2.0.0",
    "react-dom": "^17.0.2",
    "react-router-bootstrap": "^0.25.0",
    "react-router-dom": "^5.3.0",
    "react-scripts": "4.0.3",
    "web-vitals": "^1.1.2"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
} 

这是产品详细信息视图中错误消息的屏幕截图

这里是主屏幕页面的屏幕截图

【问题讨论】:

    标签: javascript reactjs react-hooks react-router react-bootstrap


    【解决方案1】:

    您的问题是您的.find() 方法返回undefined,因此您无法访问product 上的属性,例如.name,因为它是undefined。当回调函数没有为数组中的任何项目返回真值时,.find() 方法将返回 undefined

    在这种情况下,只有当您的产品 id 与您的 URL 中使用的 id 的 id 完全匹配(在值和类型上)时,您的回调才会返回 true

    p._id === match.params.id
    

    但是,上面永远不会是true,因为你的数据中的p._id是一个数字类型,而match.params.id是一个字符串类型,所以在严格的平等=== 下,这两者永远不会被认为是平等的。结果,.find() 永远找不到匹配项,而您得到undefind。相反,您可以使用“松散”相等比较==,它不需要匹配类型:

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

    或者,您可以使用Number() 等方法手动转换类型并坚持使用===

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

    【讨论】:

    • 这些信息对我帮助很大!!非常感谢你
    • @JabidJimenez 不用担心!
    【解决方案2】:

    match.params.id 字符串类型,所以你应该解析字符串,因为_id 是int,你可以使用parseInt(1)

        import React from "react";
        import products from "../products";
    
        const ProductDetails = ({ match }) => {
           const product = products.find((p) => p._id === parseInt(match.params.id));
    
           return <div>{product.name}</div>;
        };
    
        export default ProductDetails;
    

    你可以看到完整的文档https://reactrouter.com/web/api/match

    【讨论】:

      【解决方案3】:
      Try this: Make changes in below two files only.
      
      For ProductDetails.js
      
      import React from "react";
      import products from "../products";
      import { useParams } from 'react-router-dom'
      
      const ProductDetails = () => {
          const {id} = useParams()
          const product = products.find(p=>p._id === id)
          return <div>{product.name}</div>;
        
      }
      
      export default ProductDetails;
      

      对于 App.js

      import React from "react";
      import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
      import { Container } from "react-bootstrap";
      import Header from "./components/Header";
      import Footer from "./components/Footer";
      import HomeScreen from "./views/HomeScreen";
      import ProductDetails from "./views/ProductDetails";
      function App() {
            return (
              <Router>
                <Header/>
                <main className='py-3'>
                  <Container>
                    <Routes> 
                      <Route path ='/' element={<HomeScreen/>} exact />
                      <Route path ='/product/:id' element={<ProductDetails/>}/>
                    </Routes>
                  </Container>
                </main>
                <Footer/>
              </Router>
            );
          }
          
          export default App;
      

      【讨论】:

        【解决方案4】:

        试试这个代码。

            import React from 'react'
            import products from '../products'
            import { useParams } from 'react-router-dom'
        
            function ProductDetails() {
                const { id } = useParams();
                const product = products.find((p) => Number(p._id) === Number(id));
                return (
                    <div>
                        {product.image}
                    </div>
                )
            }
            
            export default ProductDetails
        

        【讨论】:

        • 这个答案真的可以使用一些描述/解释。
        猜你喜欢
        • 2022-09-26
        • 2021-11-10
        • 2021-11-03
        • 2021-11-08
        • 2022-01-16
        • 2021-11-25
        • 2022-08-10
        • 1970-01-01
        • 2021-12-31
        相关资源
        最近更新 更多