我是 React 新手,当我尝试从 React 应用程序的一个名为“products.js”的文件中的一组对象中获取一些“产品”时,我需要一些帮助。
问题是我能够在主屏幕中绘制数组中的产品。然而,当我尝试在我的详细产品页面上绘制这些产品时(这是一个我可以看到单个产品详细信息的页面)“ProductDetails.js”,我收到错误(无论我是否尝试带上product.name或产品.价格或其他):
类型错误:无法读取未定义的属性(读取“名称”)
为了让您了解我在说什么,我将向您分享我的代码中的一些片段,以便您了解上下文。我将从确切的错误消息开始,并以我的项目依赖项一览结束。
错误信息
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.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"
]
}
}
您的问题是您的
.find()
方法返回 undefined
,因此您无法访问 product
上的属性,例如 .name
,因为它是 undefined
。当回调函数没有为数组中的任何项目返回真值时,.find()
方法将返回undefined
。
在这种情况下,只有当您的产品 ID 与 URL 中使用的 ID 完全匹配(无论是值还是类型)时,您的回调才会返回
true
:
p._id === match.params.id
但是,上面的永远不会是
true
,因为你数据中的p._id
是number类型,而match.params.id
是string类型,所以在严格相等的情况下,两者永远不会被认为是相等的===
。结果,.find()
永远找不到匹配项,而您得到 undefind
。相反,您可以使用“松散”相等比较 ==
,它不需要类型匹配:
const product = products.find((p) => p._id == match.params.id);
或者,您可以使用
Number()
等方法手动转换类型并坚持使用 ===
:
const product = products.find((p) => p._id === Number(match.params.id));
我注意到这个问题已经引起了相当多的关注,所以我想我应该添加另一个你可能会看到这个错误的常见原因(注意这些原因不适用于操作代码)。
首先,该错误意味着您使用
.name
的任何内容都有一个值 undefined
。通常,如果您使用 fetch()
等内容进行 API 调用,或者在 useEffect()
中执行其他异步任务(设置您正在使用 .name
的任何内容的值),则可能会发生这种情况。有两种方法可以解决这个问题,一种方法是使用 可选链 来防止访问 .name
属性(如果对象是 null
或 undefined
,例如:)
<strong>{product?.name}</strong>
或者,另一种方法是分配您的状态值,以便它最初不是未定义的,例如:
const [product, setProduct] = useState({}); // <-- using `product.name` now works, whereas doing `useState()` wouldn't work
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;
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;
试试这个代码。
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
我正在 React Native Expo 项目中工作,当我运行命令“npx expo start”时,它显示此错误。我通过运行命令修复了它
npx 博览会开始--重置缓存
对我有用,你也可以试试。