React中props传递异常:product属性为何无法正确传入?
我正在用ProductCard组件将product对象传递至ProductPage页面,product对象应包含id、categoryId、name、price和img键值对。我通过对产品数组过滤、映射,获取特定分类的产品后将整个对象传入组件,但目前打印product得到undefined,页面也无内容渲染。
ProductsPage代码
const ProductsPage = () => { const [toggle, setToggle] = useState(false); const [categoryId, setCategoryId] = useState(0); const show = (id) => { if (toggle === id) return setToggle(null); setToggle(id); setCategoryId(id); }; return ( <div className="products-page"> <div className="container"> <section className="product-banner"> <h3>All Products</h3> </section> <div className="product-categories"> {categories.map((cat) => ( <div key={cat.id}> <section onClick={() => show(cat.id)} className="cat-toggle" > <h4>{cat.name}</h4> </section> {toggle === cat.id && ( <section className="products"> {products.filter((item) => item.categoryId === categoryId).map(filteredProduct => ( <ProductCard key={filteredProduct.id} product={filteredProduct} /> ))} </section> )} </div> ))} </div> </div> </div> ); };
ProductCard组件代码
import React from "react"; import { Link } from "react-router-dom"; import "./ProductCard.scss"; const ProductCard = ({ product }) => { return ( <Link className="link" to={`/products/${product.id}`}> <div className="product-card"> <div className="product-img"> <img src={product.img} alt={product.name} /> </div> <div className="product-info"> <p>${product.price}</p> <h5>{product.name}</h5> </div> </div> </Link> ); }; export default ProductCard;
我尝试过用react-router-dom的Link组件通过state={{ product: {product} }}传递属性,但结果一致。
问题排查与解决方法
1. 状态更新异步导致过滤不匹配
show函数中同时更新toggle和categoryId,但React状态更新是异步的,点击分类后,第一次渲染时categoryId可能还未更新,导致过滤条件失效;另外初始categoryId设为0,如果产品数组中没有categoryId=0的产品,初始过滤结果为空。
解决:直接使用当前循环的cat.id做过滤,无需依赖categoryId状态:
{toggle === cat.id && ( <section className="products"> {products.filter((item) => item.categoryId === cat.id).map(filteredProduct => ( <ProductCard key={filteredProduct.id} product={filteredProduct} /> ))} </section> )}
2. 未处理product为空的边界情况
如果过滤结果为空或product未正确传递,直接访问product.id会报错,需添加空值检查:
const ProductCard = ({ product }) => { if (!product) return null; return ( <Link className="link" to={`/products/${product.id}`}> <div className="product-card"> <div className="product-img"> <img src={product.img} alt={product.name} /> </div> <div className="product-info"> <p>${product.price}</p> <h5>{product.name}</h5> </div> </div> </Link> ); };
3. 检查数据源正确性
确认products数组中每个元素都包含categoryId、id等必填字段,且categories的id与products的categoryId完全匹配,可以在过滤前打印products和cat.id验证匹配情况。
4. Link传参的正确写法
如果要跳转到ProductPage时传递product数据,正确写法是:
<Link className="link" to={`/products/${product.id}`} state={{ product }}>
在ProductPage中通过useLocation接收:
import { useLocation } from 'react-router-dom'; const ProductPage = () => { const location = useLocation(); const product = location.state?.product; // 后续渲染逻辑 };
避免写成state={{ product: {product} }},这会导致product被嵌套在另一个对象中,无法直接获取。
内容的提问来源于stack exchange,提问作者skyeNoLimit

