Next.js集成Edamam API时点击详情页出现404错误求助
解决Next.js集成Edamam API时食谱详情页404错误
我在将Next.js与Edamam API集成过程中,搜索功能可正常获取数据,但点击「查看详情」跳转食谱详情页时出现404页面未找到错误。浏览器跳转URL为:http://localhost:3000/recipes/the-crispy-egg?uri=http%3A%2F%2Fwww.edamam.com%2Fontologies%2Fedamam.owl%23recipe_db742742099859a8053b992dd3c1f452
相关代码文件
/components/RecipeCard.tsx(展示搜索到的食谱列表)
import React from 'react'; import Link from 'next/link'; import { slugify } from '@/app/utils/slugify'; import { Box, Card, CardContent, CardMedia, Container, Grid, Typography } from '@mui/material'; interface RecipeCardProps { recipe: { uri: string; label: string; image: string; ingredientLines: string[]; }; } const RecipeCard: React.FC<RecipeCardProps> = ({ recipe }) => { const slug = slugify(recipe.label); return ( <Card> <CardMedia component="img" height="140" image={recipe.image} alt={recipe.label} /> <CardContent> <Typography gutterBottom variant="h5" component="div"> {recipe.label} </Typography> <Link href={`/recipes/${slug}?uri=${encodeURIComponent(recipe.uri)}`} passHref> <Typography variant="body2" color="primary" component="a"> View Details </Typography> </Link> </CardContent> </Card> ); }; export default RecipeCard;
/pages/recipes/[slug].tsx(预期展示详情页的文件)
import { useRouter } from 'next/router'; import { useEffect, useState } from 'react'; import axios from 'axios'; import { Container, Typography, CircularProgress, Card, CardContent, CardMedia } from '@mui/material'; const APP_ID = process.env.NEXT_PUBLIC_APP_ID; const APP_KEY = process.env.NEXT_PUBLIC_APP_KEY; interface RecipeDetailsProps { label: string; image: string; ingredientLines: string[]; calories: number; } const RecipeDetail = () => { const router = useRouter(); const { slug } = router.query; const [recipe, setRecipe] = useState<RecipeDetailsProps | null>(null); const [loading, setLoading] = useState(true); useEffect(() => { const fetchRecipe = async () => { if (!slug) return; const uri = decodeURIComponent(router.query.uri as string); const recipeId = uri.split('#recipe_')[1]; try { const response = await axios.get( `https://api.edamam.com/api/recipes/v2/${recipeId}`, { params: { type: 'public', app_id: APP_ID, app_key: APP_KEY, }, } ); setRecipe(response.data.recipe); setLoading(false); } catch (error) { console.error('Error fetching recipe:', error); setLoading(false); } }; fetchRecipe(); }, [slug]); if (loading) { return <CircularProgress />; } if (!recipe) { return <Typography variant="h6">Recipe not found</Typography>; } return ( <Container> <Card> <CardMedia component="img" height="140" image={recipe.image} alt={recipe.label} /> <CardContent> <Typography gutterBottom variant="h5" component="div"> {recipe.label} </Typography> <Typography variant="body2" color="textSecondary" component="p"> {recipe.ingredientLines.join(', ')} </Typography> <Typography variant="body2" color="textSecondary" component="p"> Calories: {Math.round(recipe.calories)} </Typography> </CardContent> </Card> </Container> ); }; export default RecipeDetail;
排查与解决方案
1. 确认路由文件路径正确性
- 检查
/pages/recipes/[slug].tsx文件是否存在,目录名recipes、文件名[slug].tsx的拼写和大小写是否完全匹配(Linux/macOS环境下Next.js区分大小写)。 - 若使用Next.js 13+混合了App Router和Pages Router,确保Pages Router的路由规则未被覆盖,可暂时禁用App Router测试。
2. 修正Link组件用法(Pages Router场景)
Pages Router下的Link组件无需passHref属性(仅自定义组件时需要),调整代码如下:
<Link href={`/recipes/${slug}?uri=${encodeURIComponent(recipe.uri)}`}> <Typography variant="body2" color="primary" component="a"> View Details </Typography> </Link>
3. 完善useEffect依赖项
原代码中useEffect仅监听slug,但请求逻辑还依赖router.query.uri,需补充依赖并增加参数校验:
useEffect(() => { const fetchRecipe = async () => { // 同时校验slug和uri参数 if (!slug || !router.query.uri) return; const uri = decodeURIComponent(router.query.uri as string); const recipeId = uri.split('#recipe_')[1]; try { const response = await axios.get( `https://api.edamam.com/api/recipes/v2/${recipeId}`, { params: { type: 'public', app_id: APP_ID, app_key: APP_KEY, }, } ); setRecipe(response.data.recipe); setLoading(false); } catch (error) { console.error('Error fetching recipe:', error); setLoading(false); } }; fetchRecipe(); }, [slug, router.query.uri]); // 补充router.query.uri到依赖数组
4. 验证slug生成有效性
检查slugify函数是否生成合法的路由路径(无特殊字符、空格替换为连字符),示例实现:
export const slugify = (text: string) => { return text .toString() .toLowerCase() .replace(/\s+/g, '-') .replace(/[^\w\-]+/g, '') .replace(/\-\-+/g, '-') .replace(/^-+/, '') .replace(/-+$/, ''); };
5. 重启开发服务器
Next.js开发服务器可能缓存路由规则,重启后可加载新的路由配置。
内容的提问来源于stack exchange,提问作者user17449555
相关产品推荐
相关产品推荐

