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

如何用React Hooks实现餐厅菜单API数据的类别筛选功能?

餐厅菜单按类别筛选功能实现方案

问题描述

已基于React的useState、useEffect Hooks完成餐厅菜单页面的API数据获取与类别tab切换基础功能,但尚未实现按类别名称筛选数据的需求,需要修改代码实现仅展示指定类别数据的功能。当前代码如下:

import React, { useState, useEffect } from 'react';

const Menu = () => {

    /*Toggle sidemenu start*/

    const [toggleState, setToggleState] = useState(1);

    const toggleTab = (index) =>{
        setToggleState(index);
    }

    /*Toggle sidemenu end*/

    /* API Data start */

    const [data, setData] = useState();

    useEffect(() => {
        async function fetchData() {
          try {
            const response = await fetch('https://63b040676a74151a1bbcf341.mockapi.io/restaurantmenu')
            const data = await response.json();
            setData(data);
            console.log("data")
          } catch (error) {
            console.error(error);
          }
        }
    
        fetchData();
      }, []);

    /* API Data end */

  return (
    
    <div className='main-content'>
        <div className='restaurant-card'>
            <div className='image'>
                <img src='/images/kfc.png'/>
            </div>
            <div className='restaurant-details'>
                <h2>KFC</h2>
                <p>Abids, Hyderabad</p>
                <p><img src='/images/rating.png'/><span>4.5 Rating | 09:00 A.M - 11:00 P.M</span></p>
            </div>
        </div>
        <div className='item-category'>
            <h3>Categories</h3>
            <ul>
                <li className={toggleState === 1 ? "tabs active" : "tabs"} onClick={()=>toggleTab(1)}>Pizza</li>
                <li className={toggleState === 2 ? "tabs active" : "tabs"} onClick={()=>toggleTab(2)}>Bread</li>
                <li className={toggleState === 3 ? "tabs active" : "tabs"} onClick={()=>toggleTab(3)}>Shakes</li>
                <li className={toggleState === 4 ? "tabs active" : "tabs"} onClick={()=>toggleTab(4)}>Ice Cream</li>
                <li className={toggleState === 5 ? "tabs active" : "tabs"} onClick={()=>toggleTab(5)}>Cakes</li>
                <li className={toggleState === 6 ? "tabs active" : "tabs"} onClick={()=>toggleTab(6)}>Juices</li>
            </ul>
            
        </div>
        <div className='item-list'>
            <div className="box">
                <input type="text" className="search-input" placeholder="Search for dishes"/>
                <img src='/images/search.png'/>
            </div>
            <div className="content">
                {
                    data 
                    ? 
                        (
                        <div>
                            <div>
                                {data.map(item =>
                                    <div>
                                        <h2>{item.Category}</h2>
                                        <div className='items' key={item.id}>
                                            <ul>
                                                <li>{item.Type}</li>
                                                <li>{item.Name}</li>
                                                <li>₹ {item.Price}</li>
                                                <div className='hr'></div>
                                            </ul>
                                        </div>
                                    </div>
                                )}
                        </div>
                        </div>
                        ) 
                    : 
                        (<div>Loading...</div>)
                }
            </div>
        </div> 
    </div>
  )
}

export default Menu;

实现方案

核心思路

将当前基于数字索引的tab切换,改为直接绑定类别名称,通过filter方法筛选出对应类别的数据后再渲染。

具体修改步骤

  1. 替换激活状态存储方式
    把原来存储数字索引的toggleState,改为存储类别名称的activeCategory,初始值设为默认选中的类别(比如"Pizza"):

    const [activeCategory, setActiveCategory] = useState("Pizza");
    
  2. 修改tab切换函数
    让toggleTab直接接收类别名称作为参数,更新激活状态:

    const toggleTab = (category) => {
        setActiveCategory(category);
    };
    
  3. 更新tab项的选中判断逻辑
    将每个tab的className判断条件改为对比类别名称:

    <li className={activeCategory === "Pizza" ? "tabs active" : "tabs"} onClick={()=>toggleTab("Pizza")}>Pizza</li>
    <!-- 其他类别项同理修改 -->
    
  4. 添加数据筛选逻辑
    在组件内计算筛选后的数据,匹配当前激活的类别:

    const filteredData = data?.filter(item => item.Category === activeCategory) || [];
    
  5. 修改渲染逻辑
    用筛选后的filteredData替代原data进行渲染,同时优化类别标题的展示(避免重复渲染同一类别标题):

    {data ? (
        filteredData.length > 0 ? (
            <div>
                <h2>{activeCategory}</h2>
                {filteredData.map(item => (
                    <div className='items' key={item.id}>
                        <ul>
                            <li>{item.Type}</li>
                            <li>{item.Name}</li>
                            <li>₹ {item.Price}</li>
                            <div className='hr'></div>
                        </ul>
                    </div>
                ))}
            </div>
        ) : (
            <div>No items found in this category</div>
        )
    ) : (
        <div>Loading...</div>
    )}
    

完整修改后的代码

import React, { useState, useEffect } from 'react';

const Menu = () => {
    // 直接存储当前激活的类别名称
    const [activeCategory, setActiveCategory] = useState("Pizza");

    const toggleTab = (category) => {
        setActiveCategory(category);
    };

    const [data, setData] = useState();

    useEffect(() => {
        async function fetchData() {
            try {
                const response = await fetch('https://63b040676a74151a1bbcf341.mockapi.io/restaurantmenu')
                const data = await response.json();
                setData(data);
            } catch (error) {
                console.error(error);
            }
        }

        fetchData();
    }, []);

    // 筛选当前激活类别的数据
    const filteredData = data?.filter(item => item.Category === activeCategory) || [];

    return (
        <div className='main-content'>
            <div className='restaurant-card'>
                <div className='image'>
                    <img src='/images/kfc.png'/>
                </div>
                <div className='restaurant-details'>
                    <h2>KFC</h2>
                    <p>Abids, Hyderabad</p>
                    <p><img src='/images/rating.png'/><span>4.5 Rating | 09:00 A.M - 11:00 P.M</span></p>
                </div>
            </div>
            <div className='item-category'>
                <h3>Categories</h3>
                <ul>
                    <li className={activeCategory === "Pizza" ? "tabs active" : "tabs"} onClick={()=>toggleTab("Pizza")}>Pizza</li>
                    <li className={activeCategory === "Bread" ? "tabs active" : "tabs"} onClick={()=>toggleTab("Bread")}>Bread</li>
                    <li className={activeCategory === "Shakes" ? "tabs active" : "tabs"} onClick={()=>toggleTab("Shakes")}>Shakes</li>
                    <li className={activeCategory === "Ice Cream" ? "tabs active" : "tabs"} onClick={()=>toggleTab("Ice Cream")}>Ice Cream</li>
                    <li className={activeCategory === "Cakes" ? "tabs active" : "tabs"} onClick={()=>toggleTab("Cakes")}>Cakes</li>
                    <li className={activeCategory === "Juices" ? "tabs active" : "tabs"} onClick={()=>toggleTab("Juices")}>Juices</li>
                </ul>
            </div>
            <div className='item-list'>
                <div className="box">
                    <input type="text" className="search-input" placeholder="Search for dishes"/>
                    <img src='/images/search.png'/>
                </div>
                <div className="content">
                    {data ? (
                        filteredData.length > 0 ? (
                            <div>
                                <h2>{activeCategory}</h2>
                                {filteredData.map(item => (
                                    <div className='items' key={item.id}>
                                        <ul>
                                            <li>{item.Type}</li>
                                            <li>{item.Name}</li>
                                            <li>₹ {item.Price}</li>
                                            <div className='hr'></div>
                                        </ul>
                                    </div>
                                ))}
                            </div>
                        ) : (
                            <div>No items found in this category</div>
                        )
                    ) : (
                        <div>Loading...</div>
                    )}
                </div>
            </div>
        </div>
    )
}

export default Menu;

内容的提问来源于stack exchange,提问作者sai charan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 08:40:27