Next.js部署Firebase遇/Cartoon页面导出错误,求解决方案
问题根源分析
你的导出错误核心原因有两个:
- 参数缺失导致API请求失败:静态导出时Next.js无法自动获取
page组件的name参数,使得请求URL中的${name}为undefined,返回的API结果大概率没有results数组,访问cartoon.results[0]直接抛出错误。 - App Router适配错误:你尝试的
getStaticProps在Next.js 13+ App Router中已被废弃,axios只是替换请求库没有解决参数问题,'use client'转为客户端组件后,静态导出阶段仍会尝试预渲染,参数缺失的问题依然存在。
解决方案
根据你的路由需求,分两种场景处理:
场景1:动态路由(每个卡通对应独立页面,如/Cartoon/SpongeBob)
1. 调整路由结构
将页面文件移动到app/Cartoon/[name]/page.js,通过路由参数获取name。
2. 编写页面代码
// 生成静态导出所需的路由参数列表,可从数据源动态获取 export async function generateStaticParams() { return [ { name: "SpongeBob" }, { name: "Rick and Morty" }, // 添加更多需要预渲染的卡通名称 ]; } export default async function CartoonPage({ params }) { const { name } = params; try { // 对name进行URI编码,避免特殊字符导致请求错误 const response = await fetch(`https://api.themoviedb.org/3/search/tv?api_key=24a1f89401be144ce02466512297e932&query=${encodeURIComponent(name)}&include_adult=true&language=en-US&page=1`); if (!response.ok) throw new Error("API请求失败"); const cartoon = await response.json(); // 处理无结果的情况 if (!cartoon.results || cartoon.results.length === 0) { return <div className='h-72 w-40 rounded-xl flex items-center justify-center bg-zinc-900'>未找到相关卡通</div>; } const firstResult = cartoon.results[0]; return ( <div className='h-72 w-40 rounded-xl'> <div> <a href={`/Cartoon/${name}`}> <img className='rounded-t-xl' src={`https://www.themoviedb.org/t/p/w600_and_h900_bestv2${firstResult.poster_path}`} alt={firstResult.name} /> </a> </div> <div className='h-12 rounded-b-xl bg-zinc-900 flex items-center justify-center p-2'> <h4 className='h-fit text-white'>{firstResult.name}</h4> </div> </div> ); } catch (err) { console.error("数据加载失败:", err); return <div className='h-72 w-40 rounded-xl flex items-center justify-center bg-zinc-900'>加载失败</div>; } }
场景2:查询参数传递(如/Cartoon?name=SpongeBob)
编写客户端组件代码
'use client'; import { useEffect, useState } from 'react'; import { useSearchParams } from 'next/navigation'; export default function CartoonPage() { const searchParams = useSearchParams(); const name = searchParams.get('name'); const [cartoon, setCartoon] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(false); useEffect(() => { if (!name) return; const fetchData = async () => { try { setLoading(true); const response = await fetch(`https://api.themoviedb.org/3/search/tv?api_key=24a1f89401be144ce02466512297e932&query=${encodeURIComponent(name)}&include_adult=true&language=en-US&page=1`); if (!response.ok) throw new Error("API请求失败"); const data = await response.json(); setCartoon(data); setError(false); } catch (err) { console.error(err); setError(true); } finally { setLoading(false); } }; fetchData(); }, [name]); if (loading) return <div className='h-72 w-40 rounded-xl flex items-center justify-center bg-zinc-900'>加载中...</div>; if (error) return <div className='h-72 w-40 rounded-xl flex items-center justify-center bg-zinc-900'>加载失败</div>; if (!cartoon?.results || cartoon.results.length === 0) return <div className='h-72 w-40 rounded-xl flex items-center justify-center bg-zinc-900'>未找到相关卡通</div>; const firstResult = cartoon.results[0]; return ( <div className='h-72 w-40 rounded-xl'> <div> <a href={`/Cartoon?name=${name}`}> <img className='rounded-t-xl' src={`https://www.themoviedb.org/t/p/w600_and_h900_bestv2${firstResult.poster_path}`} alt={firstResult.name} /> </a> </div> <div className='h-12 rounded-b-xl bg-zinc-900 flex items-center justify-center p-2'> <h4 className='h-fit text-white'>{firstResult.name}</h4> </div> </div> ); }
内容的提问来源于stack exchange,提问作者Wissam Salem
相关产品推荐
相关产品推荐

