You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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参数里:

  1. 配置路由:
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>
  );
}
  1. 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>
  );
}
  1. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 10:17:42