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

React电商网站商品详情页点击空白,出现ReferenceError错误求助

问题修复方案

错误根源分析

  1. 变量初始化顺序错误:useEffect中第一行setProductData(productData);调用了尚未初始化的变量,且该productData状态变量在组件中完全未被使用,属于冗余代码,直接触发ReferenceError。
  2. 类型不匹配:useParams()获取的id是字符串类型,而数据文件中商品id是数字,直接用item.id === id无法匹配到目标商品,导致product始终为空对象,渲染时访问属性会引发错误。
  3. 依赖数组缺失:useEffect依赖数组为空,当路由参数id变化时不会重新执行数据筛选,切换商品时无法更新页面内容。

修改后的商品详情页(Product)代码

import React, { useState, useEffect } from "react";
import { Link, useParams } from "react-router-dom";
import Marquee from "react-fast-marquee";
import { useDispatch } from "react-redux";
import { addCart } from "../redux/action";
import data from "../components/data.json";
import { Footer, Navbar } from "../components";

const Product = () => {
  const { id } = useParams();
  const [product, setProduct] = useState(null);
  const [similarProducts, setSimilarProducts] = useState([]);
  const dispatch = useDispatch();

  useEffect(() => {
    // 将路由id转为数字,匹配数据中的id类型
    const targetId = Number(id);
    // 筛选目标商品
    const targetProduct = data.find(item => item.id === targetId);
    
    if (targetProduct) {
      setProduct(targetProduct);
      // 筛选同分类相似商品
      const similarData = data.filter(item => item.category === targetProduct.category);
      setSimilarProducts(similarData);
    }
  }, [id]); // 添加id到依赖数组,路由变化时重新执行

  const addProduct = (product) => {
    dispatch(addCart(product));
  };

  const ShowProduct = () => {
    // 当product为空时显示加载提示,避免报错
    if (!product) {
      return <div className="container my-5 py-2 text-center">加载中...</div>;
    }
    
    return (
      <>
        <div className="container my-5 py-2">
          <div className="row">
            <div className="col-md-6 col-sm-12 py-3">
              <img
                className="img-fluid"
                src={product.image}
                alt={product.title}
                width="400"
                height="400"
              />
            </div>
            <div className="col-md-6 py-5">
              <h4 className="text-uppercase text-muted">{product.category}</h4>
              <h1 className="display-5">{product.title}</h1>
              <h3 className="display-6 my-4">${product.price}</h3>
              <p className="lead">{product.description}</p>
              <button
                className="btn btn-outline-dark"
                onClick={() => addProduct(product)}
              >
                Add to Cart
              </button>
              <Link to="/cart" className="btn btn-dark mx-3">
                Go to Cart
              </Link>
            </div>
          </div>
        </div>
      </>
    );
  };

  const ShowSimilarProduct = () => {
    return (
      <>
        <div className="py-4 my-4">
          <div className="d-flex">
            {similarProducts.map((item) => {
              return (
                <div key={item.id} className="card mx-4 text-center">
                  <img
                    className="card-img-top p-3"
                    src={item.image}
                    alt="Card"
                    height={300}
                    width={300}
                  />
                  <div className="card-body">
                    <h5 className="card-title">
                      {item.title.substring(0, 15)}...
                    </h5>
                  </div>
                  <div className="card-body">
                    <Link
                      to={`/product/${item.id}`}
                      className="btn btn-dark m-1"
                    >
                      Buy Now
                    </Link>
                    <button
                      className="btn btn-dark m-1"
                      onClick={() => addProduct(item)}
                    >
                      Add to Cart
                    </button>
                  </div>
                </div>
              );
            })}
          </div>
        </div>
      </>
    );
  };

  return (
    <>
      <Navbar />
      <div className="container">
        <div className="row">
          {ShowProduct()}
          <div className="row my-5 py-5">
            <div className="d-none d-md-block">
              <h2 className="">You may also Like</h2>
              <Marquee pauseOnHover={true} pauseOnClick={true} speed={50}>
                {ShowSimilarProduct()}
              </Marquee>
            </div>
          </div>
        </div>
      </div>
      <Footer />
    </>
  );
};

export default Product;

关键修改说明

  • 移除了冗余的productData状态变量及错误的setProductData调用,解决初始化顺序错误。
  • 将路由参数id转为数字类型,确保和数据中的id类型匹配,正确筛选目标商品。
  • 给useEffect添加id依赖,路由参数变化时自动重新获取商品数据。
  • 添加了product为空时的加载提示,避免渲染空对象属性引发的错误。
  • 优化了商品链接的写法,使用模板字符串/product/${item.id}更简洁。

内容的提问来源于stack exchange,提问作者Alex Amiriyan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 01:11:32