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

Next.js动态页面无法获取API数据 求调试帮助

Next.js动态页面数据获取异常排查

问题描述

在Next.js动态页面(路径:src\app\Stocks[ticker]\page.js)中遇到数据获取异常:页面可正常加载,但无法从API获取并展示数据。已确认API端点功能正常(直接访问可返回数据),测试多个API均仅在控制台有响应,页面始终为空。

页面代码

"use client";
import { useRouter } from "next/navigation";
import { useEffect, useState } from "react";

const StockDetailsPage = () => {
  const router = useRouter();
  const [stockData, setStockData] = useState([]);

  useEffect(() => {
    fetchData();
  }, []);

  const fetchData = async () => {
    try {
      const apiUrl = "http://localhost:4000/stocks";
      const response = await fetch(apiUrl);
      if (!response.ok) {
        throw new Error("Failed to fetch data");
      }
      const data = await response.json();
      console.log("API Response:", data); // Log the API response
      if (!data || !data.stocks || !Array.isArray(data.stocks)) {
        throw new Error("Invalid data format");
      }
      setStockData(data.stocks); // Assuming the data is structured with a "stocks" array
    } catch (error) {
      console.error("Error fetching data:", error);
      setStockData([]);
    }
  };

  return (
    <>
      <div className="bg-background dark:bg-Background flex flex-col pl-[15px] pr-[15px] sm:pl-[100px] sm:pr-[40px] pt-2 sm:pt-4">
        <h1 className="mb-2">Stock Data</h1>
        <div className="rounded-2xl mb-4 sm:mb-8 dark:bg-gradient-to-tl from-[#101010] dark:to-[#161616] border dark:border-[#252525] bg-white flex-grow text-center">
          {stockData.map((stock) => (
            <div key={stock.ticker_id} className="p-4">
              <h2>{stock.ticker_id}</h2>
              <p>{stock.company_name}</p>
              <p>Price: {stock.price}</p>
              <p>Change: {stock.change}</p>
              <p>Change Percent: {stock.change_percent}</p>
              <p>Previous Close: {stock.prev_close}</p>
              <p>Open: {stock.open}</p>
              <p>Low: {stock.low}</p>
              <p>High: {stock.high}</p>
              <p>52 Weeks High: {stock["52_weeks_high"]}</p>
              <p>52 Weeks Low: {stock["52_weeks_low"]}</p>
              <p>Market Cap: {stock.market_cap}</p>
              <p>Volume: {stock.volume}</p>
              <p>Average Volume (3 Months): {stock.avg_vol_3_months}</p>
              <p>Turn Over: {stock.turn_over}</p>
              <p>Range: {stock.range}</p>
              <p>Shares Outstanding: {stock.shares_outstanding}</p>
              <p>Shares Float: {stock.shares_float}</p>
            </div>
          ))}
        </div>
      </div>
    </>
  );
};

export default StockDetailsPage;

排查与解决方案

1. 数据结构匹配问题

代码中硬编码假设API返回数据包含stocks数组,但实际控制台打印的响应可能结构不符:

  • 如果API直接返回股票数组(而非带stocks键的对象),data.stocks会是undefined,触发格式错误,导致stockData被设为空数组。
  • 修改数据处理逻辑:
    const fetchData = async () => {
      try {
        const apiUrl = "http://localhost:4000/stocks";
        const response = await fetch(apiUrl);
        if (!response.ok) {
          throw new Error("Failed to fetch data");
        }
        const data = await response.json();
        console.log("API Response:", data);
        // 调整格式校验逻辑,适配直接返回数组的情况
        if (!Array.isArray(data)) {
          throw new Error("Invalid data format");
        }
        setStockData(data);
      } catch (error) {
        console.error("Error fetching data:", error);
        setStockData([]);
      }
    };
    

2. 动态路由参数未正确使用

这是[ticker]动态页面,但当前代码未利用路由参数请求对应个股数据:

  • App Router中获取动态参数应使用useParams而非useRouter,useRouter的query已不再适用。
  • 修改代码获取ticker参数并请求对应数据:
    "use client";
    // 替换useRouter为useParams
    import { useParams } from "next/navigation";
    import { useEffect, useState } from "react";
    
    const StockDetailsPage = () => {
      const params = useParams();
      const ticker = params.ticker;
      // 如果请求单个股票,初始状态改为null而非数组
      const [stockData, setStockData] = useState(null);
    
      useEffect(() => {
        if (ticker) fetchData();
      }, [ticker]);
    
      const fetchData = async () => {
        try {
          // 请求对应个股的API端点
          const apiUrl = `http://localhost:4000/stocks/${ticker}`;
          const response = await fetch(apiUrl);
          if (!response.ok) {
            throw new Error("Failed to fetch data");
          }
          const data = await response.json();
          console.log("API Response:", data);
          setStockData(data);
        } catch (error) {
          console.error("Error fetching data:", error);
          setStockData(null);
        }
      };
    
      return (
        <>
          <div className="bg-background dark:bg-Background flex flex-col pl-[15px] pr-[15px] sm:pl-[100px] sm:pr-[40px] pt-2 sm:pt-4">
            <h1 className="mb-2">Stock Data</h1>
            <div className="rounded-2xl mb-4 sm:mb-8 dark:bg-gradient-to-tl from-[#101010] dark:to-[#161616] border dark:border-[#252525] bg-white flex-grow text-center">
              {stockData ? (
                <div className="p-4">
                  <h2>{stockData.ticker_id}</h2>
                  <p>{stockData.company_name}</p>
                  <p>Price: {stockData.price}</p>
                  {/* 其余字段渲染 */}
                </div>
              ) : (
                <p className="p-4">加载中或无数据</p>
              )}
            </div>
          </div>
        </>
      );
    };
    
    export default StockDetailsPage;
    

3. 添加空状态提示

当前代码在stockData为空时无任何提示,导致页面看起来空白。添加空状态:

{stockData.length === 0 ? (
  <p className="p-4">暂无股票数据</p>
) : (
  stockData.map((stock) => (
    // 现有渲染逻辑
  ))
)}

4. 跨域验证(可选)

虽然控制台能拿到响应,但仍需确认API服务器是否配置了CORS,允许前端域名(如http://localhost:3000)访问。如果存在跨域限制,即使控制台打印响应,数据处理也可能被中断。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 02:34:59