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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 05:14:55