React Router中子组件传值问题:如何将ReadProducts的产品ID传给ReadOne
如何在React组件间传递产品ID以展示单个产品
嘿,我来帮你搞定这个组件传值的问题!根据你描述的组件结构,最直接靠谱的方案是状态提升——把选中的产品ID放到父组件的状态里,再分别传递给ReadProducts(用来触发ID更新)和ReadOne(用来获取/展示对应产品)。下面是具体的实现步骤和代码示例:
1. 在父组件中统一管理状态
父组件作为数据的中枢,需要维护两个核心状态:所有产品的列表,以及当前选中的产品ID。这样就能把ReadProducts和ReadOne的数据流串联起来:
import { useState, useEffect } from 'react'; import ReadProducts from './ReadProducts'; import ReadOne from './ReadOne'; function ProductParent() { const [products, setProducts] = useState([]); const [selectedProductId, setSelectedProductId] = useState(null); // 这里也可以让ReadProducts自己获取产品列表,看你业务需求调整 useEffect(() => { fetch('/api/products') .then(res => res.json()) .then(data => setProducts(data)) .catch(err => console.error('获取产品列表失败:', err)); }, []); return ( <div className="product-container"> <ReadProducts products={products} onProductClick={setSelectedProductId} /> {/* 只有选中ID后才渲染ReadOne */} {selectedProductId && <ReadOne productId={selectedProductId} />} </div> ); } export default ProductParent;
2. 在ReadProducts中触发ID选择
ReadProducts负责渲染产品列表,给每个产品项添加点击事件,调用父组件传过来的方法把当前产品的ID回传给父组件:
function ReadProducts({ products, onProductClick }) { if (!products.length) return <div>产品加载中...</div>; return ( <ul className="product-list"> {products.map(product => ( <li key={product.id} onClick={() => onProductClick(product.id)} style={{ cursor: 'pointer', padding: '8px', borderBottom: '1px solid #eee' }} > {product.name} </li> ))} </ul> ); } export default ReadProducts;
3. 在ReadOne中使用传递的ID获取产品详情
拿到父组件传过来的productId后,就可以根据ID请求单个产品的数据,或者直接从父组件的产品列表里筛选(如果父组件已经存了所有数据的话):
import { useState, useEffect } from 'react'; function ReadOne({ productId }) { const [product, setProduct] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { fetch(`/api/products/${productId}`) .then(res => { if (!res.ok) throw new Error('产品不存在或请求失败'); return res.json(); }) .then(data => { setProduct(data); setLoading(false); }) .catch(err => { setError(err.message); setLoading(false); }); }, [productId]); // 当productId变化时自动重新请求数据 if (loading) return <div>加载产品详情中...</div>; if (error) return <div className="error">{error}</div>; if (!product) return null; return ( <div className="product-details"> <h2>{product.name}</h2> <p>价格: ${product.price}</p> <p>描述: {product.description}</p> {/* 其他产品信息 */} </div> ); } export default ReadOne;
可选方案:用路由传递ID(适合需要URL导航的场景)
如果你的应用需要通过URL保留产品详情页面(比如用户可以分享链接),可以用React Router把ID放到URL参数里:
- 配置路由:
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'; import ProductParent from './ProductParent'; import ReadOne from './ReadOne'; function App() { return ( <Router> <Routes> <Route path="/" element={<ProductParent />} /> <Route path="/products/:id" element={<ReadOne />} /> </Routes> </Router> ); }
- ReadProducts里用
Link跳转:
import { Link } from 'react-router-dom'; function ReadProducts({ products }) { if (!products.length) return <div>产品加载中...</div>; return ( <ul className="product-list"> {products.map(product => ( <li key={product.id} style={{ padding: '8px' }}> <Link to={`/products/${product.id}`}>{product.name}</Link> </li> ))} </ul> ); }
- ReadOne里获取URL中的ID:
import { useParams } from 'react-router-dom'; import { useState, useEffect } from 'react'; function ReadOne() { const { id } = useParams(); // 后续请求数据的逻辑和之前一致,用id代替productId即可 // ... }
这两种方案都能完美解决你的问题:状态提升适合在同一个页面内快速切换产品详情,路由方案适合需要独立页面和URL导航的场景,你可以根据自己的业务需求选~
内容的提问来源于stack exchange,提问作者Kirill
相关产品推荐
相关产品推荐

