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
相关产品推荐
相关产品推荐

