0

0

使用 React 构建食谱查找器网站

DDD

DDD

发布时间:2024-09-13 13:58:11

|

925人浏览过

|

来源于dev.to

转载

使用 react 构建食谱查找器网站

介绍

在本博客中,我们将使用 react 构建一个食谱查找网站。该应用程序允许用户搜索他们最喜欢的食谱,查看趋势或新食谱,并保存他们最喜欢的食谱。我们将利用 edamam api 获取实时食谱数据并将其动态显示在网站上。

项目概况

食谱查找器允许用户:

  • 按名称搜索食谱。
  • 查看趋势和新添加的食谱。
  • 查看各个食谱的详细信息。
  • 将食谱添加到收藏夹列表并使用 localstorage 保存数据。

特征

  • 搜索功能:用户可以通过输入查询来搜索食谱。
  • 热门食谱:显示来自 api 的当前热门食谱。
  • 新菜谱:显示来自 api 的最新菜谱。
  • 食谱详细信息:显示有关所选食谱的详细信息。
  • 收藏夹:允许用户将食谱添加到收藏夹列表,该列表保存在本地。

使用的技术

  • react:用于构建用户界面。
  • react router:用于不同页面之间的导航。
  • edamam api:用于获取食谱。
  • css:用于设计应用程序的样式。

项目结构

src/
│
├── components/
│   └── navbar.js
│
├── pages/
│   ├── home.js
│   ├── about.js
│   ├── trending.js
│   ├── newrecipe.js
│   ├── recipedetail.js
│   ├── contact.js
│   └── favorites.js
│
├── app.js
├── index.js
├── app.css
└── index.css

安装

要在本地运行此项目,请按照以下步骤操作:

  1. 克隆存储库:
   git clone https://github.com/abhishekgurjar-in/recipe-finder.git
   cd recipe-finder
  1. 安装依赖项:
   npm install
  1. 启动 react 应用程序:
   npm start
  1. 从 edamam 网站获取您的 edamam api 凭证(api id 和 api 密钥)。

  2. 在进行 api 调用的页面中添加您的 api 凭据,例如 home.js、trending.js、newrecipe.js 和 recipedetail.js。

用法

应用程序.js
import react from "react";
import navbar from "./components/navbar";
import { route, routes } from "react-router-dom";
import "./app.css";
import home from "./pages/home";
import about from "./pages/about";
import trending from "./pages/trending";
import newrecipe from "./pages/newrecipe";
import recipedetail from "./pages/recipedetail";
import contact from "./pages/contact";
import favorites from "./pages/favorites";
const app = () => {
  return (
    <>
      
      
        } />
        } />
        } />
        } />
        } />
        } />
        } />
        } />
      
   

made with ❤️ by abhishek gurjar

); }; export default app;
主页.js

这是用户可以使用 edamam api 搜索食谱的主页。

import react, { usestate, useref, useeffect } from "react";
import { iosearch } from "react-icons/io5";
import { link } from "react-router-dom";


const home = () => {
  const [query, setquery] = usestate("");
  const [recipe, setrecipe] = usestate([]);
  const recipesectionref = useref(null);

  const api_id = "2cbb7807";
  const api_key = "17222f5be3577d4980d6ee3bb57e9f00";

  const getrecipe = async () => {
    if (!query) return; // add a check to ensure the query is not empty
    const response = await fetch(
      `https://api.edamam.com/search?q=${query}&app_id=${api_id}&app_key=${api_key}`
    );
    const data = await response.json();
    setrecipe(data.hits);
    console.log(data.hits);
  };

  // use useeffect to detect changes in the recipe state and scroll to the recipe section
  useeffect(() => {
    if (recipe.length > 0 && recipesectionref.current) {
      recipesectionref.current.scrollintoview({ behavior: "smooth" });
    }
  }, [recipe]);

  // handle key down event to trigger getrecipe on enter key press
  const handlekeydown = (e) => {
    if (e.key === "enter") {
      getrecipe();
    }
  };

  return (
    

find your favourite recipe

setquery(e.target.value)} onkeydown={handlekeydown} // add the onkeydown event handler />
{recipe.map((item, index) => (
@@##@@

{item.recipe.label}

))}
); }; export default home;
trending.js

此页面获取并显示趋势食谱。

import react, { usestate, useeffect } from "react";
import { link } from "react-router-dom";

const trending = () => {
  const [trendingrecipes, settrendingrecipes] = usestate([]);
  const [loading, setloading] = usestate(true);
  const [error, seterror] = usestate(null);

  const api_id = "2cbb7807";
  const api_key = "17222f5be3577d4980d6ee3bb57e9f00";

  useeffect(() => {
    const fetchtrendingrecipes = async () => {
      try {
        const response = await fetch(
          `https://api.edamam.com/api/recipes/v2?type=public&q=trending&app_id=${api_id}&app_key=${api_key}`
        );
        if (!response.ok) {
          throw new error("network response was not ok");
        }
        const data = await response.json();
        settrendingrecipes(data.hits);
        setloading(false);
      } catch (error) {
        seterror("failed to fetch trending recipes");
        setloading(false);
      }
    };

    fetchtrendingrecipes();
  }, []);

  if (loading)
    return (
      
); if (error) return
{error}
; return (

trending recipes

{trendingrecipes.map((item, index) => (
@@##@@

{item.recipe.label}

))}
); }; export default trending;
新菜谱.js

此页面获取新食谱并显示新食谱。

import react, { usestate, useeffect } from "react";
import { link } from "react-router-dom";

const newrecipe = () => {
  const [newrecipes, setnewrecipes] = usestate([]);
  const [loading, setloading] = usestate(true);
  const [error, seterror] = usestate(null);

  const api_id = "2cbb7807";
  const api_key = "17222f5be3577d4980d6ee3bb57e9f00";

  useeffect(() => {
    const fetchnewrecipes = async () => {
      try {
        const response = await fetch(
          `https://api.edamam.com/api/recipes/v2?type=public&q=new&app_id=${api_id}&app_key=${api_key}`
        );
        if (!response.ok) {
          throw new error("network response was not ok");
        }
        const data = await response.json();
        setnewrecipes(data.hits);
        setloading(false);
      } catch (error) {
        seterror("failed to fetch new recipes");
        setloading(false);
      }
    };

    fetchnewrecipes();
  }, []);

  if (loading)
    return (
      
); if (error) return
{error}
; return (

new recipes

{newrecipes.map((item, index) => (
@@##@@

{item.recipe.label}

))}
); }; export default newrecipe;
主页.js

此页面获取并显示主页和搜索的食谱。

MedPeer科研绘图
MedPeer科研绘图

生物医学领域的专业绘图解决方案,告别复杂绘图,专注科研创新

下载
import react, { usestate, useref, useeffect } from "react";
import { iosearch } from "react-icons/io5";
import { link } from "react-router-dom";


const home = () => {
  const [query, setquery] = usestate("");
  const [recipe, setrecipe] = usestate([]);
  const recipesectionref = useref(null);

  const api_id = "2cbb7807";
  const api_key = "17222f5be3577d4980d6ee3bb57e9f00";

  const getrecipe = async () => {
    if (!query) return; // add a check to ensure the query is not empty
    const response = await fetch(
      `https://api.edamam.com/search?q=${query}&app_id=${api_id}&app_key=${api_key}`
    );
    const data = await response.json();
    setrecipe(data.hits);
    console.log(data.hits);
  };

  // use useeffect to detect changes in the recipe state and scroll to the recipe section
  useeffect(() => {
    if (recipe.length > 0 && recipesectionref.current) {
      recipesectionref.current.scrollintoview({ behavior: "smooth" });
    }
  }, [recipe]);

  // handle key down event to trigger getrecipe on enter key press
  const handlekeydown = (e) => {
    if (e.key === "enter") {
      getrecipe();
    }
  };

  return (
    

find your favourite recipe

setquery(e.target.value)} onkeydown={handlekeydown} // add the onkeydown event handler />
{recipe.map((item, index) => (
@@##@@

{item.recipe.label}

))}
); }; export default home;
收藏夹.js

此页面显示最喜欢的食谱。

import react, { usestate, useeffect } from "react";
import { link } from "react-router-dom";

const favorites = () => {
  const [favorites, setfavorites] = usestate([]);

  useeffect(() => {
    const savedfavorites = json.parse(localstorage.getitem("favorites")) || [];
    setfavorites(savedfavorites);
  }, []);

  if (favorites.length === 0) {
    return 
no favorite recipes found.
; } return (

favorite recipes

    {favorites.map((recipe) => (
    @@##@@

    {recipe.label}

    ))}
); }; export default favorites;
recipedetail.js

此页面显示食谱。

import react, { usestate, useeffect } from "react";
import { useparams } from "react-router-dom";

const recipedetail = () => {
  const { id } = useparams(); // use react router to get the recipe id from the url
  const [recipe, setrecipe] = usestate(null);
  const [loading, setloading] = usestate(true);
  const [error, seterror] = usestate(null);
  const [favorites, setfavorites] = usestate([]);

  const api_id = "2cbb7807";
  const api_key = "17222f5be3577d4980d6ee3bb57e9f00";

  useeffect(() => {
    const fetchrecipedetail = async () => {
      try {
        const response = await fetch(
          `https://api.edamam.com/api/recipes/v2/${id}?type=public&app_id=${api_id}&app_key=${api_key}`
        );
        if (!response.ok) {
          throw new error("network response was not ok");
        }
        const data = await response.json();
        setrecipe(data.recipe);
        setloading(false);
      } catch (error) {
        seterror("failed to fetch recipe details");
        setloading(false);
      }
    };

    fetchrecipedetail();
  }, [id]);

  useeffect(() => {
    const savedfavorites = json.parse(localstorage.getitem("favorites")) || [];
    setfavorites(savedfavorites);
  }, []);

  const addtofavorites = () => {
    const updatedfavorites = [...favorites, recipe];
    setfavorites(updatedfavorites);
    localstorage.setitem("favorites", json.stringify(updatedfavorites));
  };

  const removefromfavorites = () => {
    const updatedfavorites = favorites.filter(
      (fav) => fav.uri !== recipe.uri
    );
    setfavorites(updatedfavorites);
    localstorage.setitem("favorites", json.stringify(updatedfavorites));
  };

  const isfavorite = favorites.some((fav) => fav.uri === recipe?.uri);

  if (loading)
    return (
      
); if (error) return
{error}
; return (
{recipe && ( <>

{recipe.label}

ingredients:

    {recipe.ingredientlines.map((ingredient, index) => (
  • {ingredient}
  • ))}

instructions:

{/* note: edamam api doesn't provide instructions directly. you might need to link to the original recipe url */}

for detailed instructions, please visit the{" "} recipe instruction

{isfavorite ? ( ) : ( )}
@@##@@
)}
); }; export default recipedetail;
联系方式.js

此页面显示联系页面。

import react, { usestate } from 'react';

const contact = () => {
  const [name, setname] = usestate('');
  const [email, setemail] = usestate('');
  const [message, setmessage] = usestate('');
  const [showpopup, setshowpopup] = usestate(false);

  const handlesubmit = (e) => {
    e.preventdefault();

    // prepare the contact details object
    const contactdetails = { name, email, message };

    // save contact details to local storage
    const savedcontacts = json.parse(localstorage.getitem('contacts')) || [];
    savedcontacts.push(contactdetails);
    localstorage.setitem('contacts', json.stringify(savedcontacts));

    // log the form data
    console.log('form submitted:', contactdetails);

    // clear form fields
    setname('');
    setemail('');
    setmessage('');

    // show popup
    setshowpopup(true);
  };

  const closepopup = () => {
    setshowpopup(false);
  };

  return (
    

contact us

setname(e.target.value)} required />
setemail(e.target.value)} required />
{showpopup && (

thank you!

your message has been submitted successfully.

)}
); }; export default contact;
关于.js

此页面显示关于页面。

import React from 'react';

const About = () => {
  return (
    

About Us

Welcome to Recipe Finder, your go-to place for discovering delicious recipes from around the world!

Our platform allows you to search for recipes based on your ingredients or dietary preferences. Whether you're looking for a quick meal, a healthy option, or a dish to impress your friends, we have something for everyone.

We use the Edamam API to provide you with a vast database of recipes. You can easily find new recipes, view detailed instructions, and explore new culinary ideas.

Features:

  • Search for recipes by ingredient, cuisine, or dietary restriction.
  • Browse new and trending recipes.
  • View detailed recipe instructions and ingredient lists.
  • Save your favorite recipes for quick access.

Our mission is to make cooking enjoyable and accessible. We believe that everyone should have the tools to cook great meals at home.

); }; export default About;

现场演示

您可以在这里查看该项目的现场演示。

结论

食谱查找网站对于任何想要发现新的和流行食谱的人来说是一个强大的工具。通过利用 react 作为前端和 edamam api 来处理数据,我们可以提供无缝的用户体验。您可以通过添加分页、用户身份验证甚至更详细的过滤选项等功能来进一步自定义此项目。

随意尝试该项目并使其成为您自己的!

制作人员

  • api:毛豆
  • 图标:react 图标

作者

abhishek gurjar 是一位专注的 web 开发人员,热衷于创建实用且功能性的 web 应用程序。在 github 上查看他的更多项目。

{item.recipe.label}{item.recipe.label}{item.recipe.label}{item.recipe.label}{recipe.label}{recipe.label}

相关专题

更多
css
css

css是层叠样式表,用来表现HTML或XML等文件样式的计算机语言,不仅可以静态地修饰网页,还可以配合各种脚本语言动态地对网页各元素进行格式化。php中文网还为大家带来html的相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

524

2023.06.15

css居中
css居中

css居中:1、通过“margin: 0 auto; text-align: center”实现水平居中;2、通过“display:flex”实现水平居中;3、通过“display:table-cell”和“margin-left”实现居中。本专题为大家提供css居中的相关的文章、下载、课程内容,供大家免费下载体验。

265

2023.07.27

css如何插入图片
css如何插入图片

cssCSS是层叠样式表(Cascading Style Sheets)的缩写。它是一种用于描述网页或应用程序外观和样式的标记语言。CSS可以控制网页的字体、颜色、布局、大小、背景、边框等方面,使得网页的外观更加美观和易于阅读。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

758

2023.07.28

css超出显示...
css超出显示...

在CSS中,当文本内容超出容器的宽度或高度时,可以使用省略号来表示被隐藏的文本内容。本专题为大家提供css超出显示...的相关文章,相关教程,供大家免费体验。

539

2023.08.01

css字体颜色
css字体颜色

CSS中,字体颜色可以通过属性color来设置,用于控制文本的前景色,字体颜色在网页设计中起到很重要的作用,具有以下表现作用:1、提升可读性;2、强调重点信息;3、营造氛围和美感;4、用于呈现品牌标识或与品牌形象相符的风格。

761

2023.08.10

什么是css
什么是css

CSS是层叠样式表(Cascading Style Sheets)的缩写,是一种用于描述网页(或其他基于 XML 的文档)样式与布局的标记语言,CSS的作用和意义如下:1、分离样式和内容;2、页面加载速度优化;3、实现响应式设计;4、确保整个网站的风格和样式保持统一。

605

2023.08.10

css三角形怎么写
css三角形怎么写

CSS可以通过多种方式实现三角形形状,本专题为大家提供css三角形怎么写的相关教程,大家可以免费体验。

560

2023.08.21

css设置文字颜色
css设置文字颜色

CSS(层叠样式表)可以用于设置文字颜色,这样做有以下好处和优势:1、增加网页的可视化效果;2、突出显示某些重要的信息或关键字;3、增强品牌识别度;4、提高网页的可访问性;5、引起不同的情感共鸣。

397

2023.08.22

Java JVM 原理与性能调优实战
Java JVM 原理与性能调优实战

本专题系统讲解 Java 虚拟机(JVM)的核心工作原理与性能调优方法,包括 JVM 内存结构、对象创建与回收流程、垃圾回收器(Serial、CMS、G1、ZGC)对比分析、常见内存泄漏与性能瓶颈排查,以及 JVM 参数调优与监控工具(jstat、jmap、jvisualvm)的实战使用。通过真实案例,帮助学习者掌握 Java 应用在生产环境中的性能分析与优化能力。

19

2026.01.20

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Sass 教程
Sass 教程

共14课时 | 0.8万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 2.9万人学习

CSS教程
CSS教程

共754课时 | 21.6万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号