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

React电商详情页点击相似产品无法更新内容问题求助

问题详情

开发电商网站时,点击产品可进入DetailPage展示完整详情,页面底部能正常从API获取并展示同类别相似产品,但点击相似产品的Link后,DetailPage页面未更新为该相似产品的内容。

原因分析

核心问题是组件未监听路由参数id的变化:

  • React Router在同一个组件的路由参数变化时,不会重新挂载组件,仅更新路由参数
  • 现有代码中,用于查找当前产品的useEffect仅依赖products,未加入id参数,导致路由id变化时,该useEffect不会重新触发,无法更新当前展示的产品数据
解决方案

1. 为产品查找的useEffect添加id依赖

修改第一个useEffect的依赖数组,加入id,确保路由参数变化时重新查找产品:

useEffect(()=>{
  // 先判断products是否存在,避免报错
  if(!products?.length) return;
  const product = products.find(product => product.id === Number(id))
  if(product){
    setItem(product)
    setMainImg(product.thumbnail)
  }
},[products, id]) // 新增id到依赖数组

2. 优化空值处理(可选但推荐)

在查找产品前先判断products是否存在,避免数组方法调用报错;同时处理找不到对应产品的情况:

useEffect(()=>{
  if(!products?.length) {
    setItem({});
    setMainImg('');
    return;
  }
  const product = products.find(product => product.id === Number(id))
  if(product){
    setItem(product)
    setMainImg(product.thumbnail)
  } else {
    // 处理找不到产品的情况,比如跳转到404或清空状态
    setItem({});
    setMainImg('');
  }
},[products, id])

3. 完整修改后的代码

import React, { useEffect, useState } from 'react'
import { useParams, Link } from 'react-router-dom'
import useFetch from '../../Component/UseFetch/useFetch'
import './detailPage.css'

const DetailPage = () => {
  const [item, setItem] = useState({}) // 初始值改为空对象更合理
  const [mainImg, setMainImg] = useState('')
  const [sameProduct, setSameProduct] = useState([])
  const { loading, products } = useFetch('https://dummyjson.com/products')
  const { id } = useParams()


  useEffect(()=>{
    if(!products?.length) {
      setItem({});
      setMainImg('');
      return;
    }
    const product = products.find(product => product.id === Number(id))
    if(product){
      setItem(product)
      setMainImg(product.thumbnail)
    } else {
      setItem({});
      setMainImg('');
    }
  },[products, id]) // 关键修改:添加id到依赖数组


  useEffect(()=>{
    if(!products?.length || !item.category) return;
    const allProduct = products.filter(product => product.category === item.category)
    setSameProduct(allProduct)
  }, [item, products])


  return (
    loading ? <div style={{
      width: '100vw',
      height: '100vh',
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'center',
      fontSize: '10vw'
    }}>Loading...</div> :
    <div>
       <div>
           <h1 className='product-headline'>Product Detail</h1>
       </div>
      <div className='product-box'>
         <div>
            {
              item?.thumbnail && (
                <div style={{height: '320px'}}>
                   <img className='main-image' src={mainImg || item.thumbnail} />
                </div>
              )
            }
            <div className='short-img-box'>
            {
            item?.images && item.images.map((image, imgId)=>{
              return <img className='short-img' key={imgId} src={image} onClick={()=> setMainImg(image) }/>
            })
            }
            </div>

         </div>
         <div>
          {
            item?.price && !isNaN(item.price) && (
              <div>
                <h1>{item.title}</h1>
                <div>
                   <span>Rating: {item.rating}</span>
                   <span>Available Stock: {item.stock}</span>
                </div>
                <div>
                  <span>{parseInt(item.price + item.price / 100 * 25)}</span><br></br>
                  <span>{item.price}</span>
                </div>
                <p>{item.description}</p>
              </div>
            )
          }
                   <button>Add to cart</button>
         </div>
      </div>

      <div>
        <h1 style={{textAlign: 'center'}}>Review section</h1>
      </div>

      <div>
        <h1 className='product-headline'>Similar Products</h1>
            <div className='products'>
                {
                    sameProduct.map((product)=>{
                      const {id, title, price, thumbnail, rating, stock} = product
                      return (
                            <div key={id} className='product'>
                                <Link to={`/detailpage/${id}`}><img src={thumbnail} /></Link>
                                <div className='product-details'>
                                  <Link className='title' to={`/detailpage/${id}`}><h3>{title}</h3></Link>
                                  <div className='price-rating'>
                                      <p>${price}</p>
                                      <p>Rating: {rating}/5</p>
                                  </div>
                                </div>
                                <button className='add-cart'>ADD TO CART</button>
                                <span className='product-stock'>Stock: {stock}</span>
                            </div>
                      )     
                    })
                }
            </div>
      </div>
    </div>
  )
}

export default DetailPage

内容的提问来源于stack exchange,提问作者M Hasan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 21:20:33