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

跨JSX组件获取API数据:商品详情页空白问题求助

解决商品列表页与详情页关联及详情页空白问题

核心问题分析

你的详情页空白主要源于以下几个错误:

  1. 路由参数获取错误:你试图通过props.art.art_id获取商品ID,但React Router的动态路由参数需要通过useParams钩子获取,而非直接从props读取。
  2. API请求路径错误:/api/galeria.json/${props.art.art_id}的路径格式不符合JSON文件的访问逻辑(除非后端专门处理这种路径),通常JSON文件是整体返回的,需要先获取全部数据再筛选对应ID的商品。
  3. 状态初始化与数据访问错误:初始状态设为数组[],但商品详情是单个对象,访问artDetails.art.name会因数组无art属性导致报错,最终页面渲染失败。
  4. 异步代码写法混乱:混用await和.then(),且多余的await res会导致逻辑错误。

分步解决方案

1. 确保路由配置正确

首先在路由配置文件中,添加动态路由指向详情页:

import { Routes, Route } from 'react-router-dom';
import ProductPage from './ProductPage';
// 导入你的列表页组件

function App() {
  return (
    <Routes>
      {/* 列表页路由 */}
      <Route path="/" element={<你的列表页组件 />} />
      {/* 详情页动态路由,:artId是参数占位符 */}
      <Route path="/art-details/:artId" element={<ProductPage />} />
    </Routes>
  );
}

2. 修正详情页代码

修改ProductPage组件,解决参数获取、API请求和状态问题:

import { useState, useEffect } from 'react';
import { useParams } from 'react-router-dom';

export default function ProductPage() {
  // 初始化状态为null,而非数组
  const [artDetails, setArtDetails] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);
  // 获取路由中的artId参数
  const { artId } = useParams();

  useEffect(() => {
    const fetchArtDetails = async () => {
      try {
        // 请求列表数据(如果没有单独的详情接口)
        const response = await fetch('/api/artProducts.json');
        if (!response.ok) throw new Error('请求失败');
        const allArts = await response.json();
        
        // 筛选对应ID的商品(注意art_id的类型,若为数字需转类型匹配)
        const targetArt = allArts.find(art => String(art.art_id) === artId);
        if (!targetArt) throw new Error('商品不存在');
        
        setArtDetails(targetArt);
      } catch (err) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    };

    fetchArtDetails();
  }, [artId]); // 依赖artId,参数变化时重新请求

  // 加载状态处理
  if (loading) return <div>加载中...</div>;
  // 错误状态处理
  if (error) return <div>出错了:{error}</div>;
  // 无数据处理
  if (!artDetails) return <div>未找到该商品</div>;

  // 正常渲染详情
  return (
    <section>
      <div>
        <h2>{artDetails.name}</h2>
        <img src={artDetails.image} alt={artDetails.name} />
        <p>价格:{String(artDetails.price).replace(".", ",")}€</p>
        {/* 渲染更多商品详情字段 */}
      </div>
    </section>
  );
}

3. 可选优化:避免重复请求(状态管理)

如果商品数据量较大,不想每次进入详情页都重新请求整个列表,可以用React Context在列表页获取数据后全局共享:

  • 在列表页获取数据后,将数据存入Context
  • 详情页直接从Context中读取数据并筛选,无需再次请求API

关键注意事项

  • 参数类型匹配:确保art_id和路由参数artId的类型一致(比如都是字符串或都是数字),否则find方法会匹配失败。
  • 错误处理:添加加载、错误状态可以避免页面空白,同时给用户明确的反馈。
  • API接口优化:如果有后端支持,最好提供单独的详情接口(比如/api/artProducts/${artId}),而非请求整个列表后筛选,提升性能。

内容的提问来源于stack exchange,提问作者Exo TV

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 22:55:18