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

React多餐段搜索框如何实现搜索结果仅在对应区域独立渲染

问题根因

  • 你在早餐搜索触发的接口请求回调中,同时给data(早餐结果集)和data2(午餐结果集)赋值了相同的返回数据,所以早餐的搜索结果会同步出现在午餐区域
  • 仅配置了监听早餐搜索词result的副作用,没有为午餐搜索词result2配置对应的搜索逻辑,午餐输入内容不会触发独立请求
  • 额外冗余问题:午餐的label标签上错误绑定了onChange事件,属于无效代码

修复后代码

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

function DietForm() {
    // 早餐相关状态
    const [breakfastQuery, setBreakfastQuery] = useState('')
    const [breakfastData, setBreakfastData] = useState([])
    // 午餐相关状态
    const [lunchQuery, setLunchQuery] = useState('')
    const [lunchData, setLunchData] = useState([])
    // 晚餐相关状态
    const [dinnerQuery, setDinnerQuery] = useState('')
    const [dinnerData, setDinnerData] = useState([])
    // 零食相关状态
    const [snackQuery, setSnackQuery] = useState('')
    const [snackData, setSnackData] = useState([])

    const [loading, setLoading] = useState(false)
    const [message, setMessage] = useState('')

    // 封装通用请求方法,避免重复代码
    const fetchFoodList = async (query, setData) => {
        if (!query.trim()) {
            setData([])
            return
        }
        const options = {
            method: 'GET',
            url: 'https://edamam-food-and-grocery-database.p.rapidapi.com/parser',
            params: {ingr: query},
            headers: {
                'x-rapidapi-host': 'edamam-food-and-grocery-database.p.rapidapi.com',
                'x-rapidapi-key': '6bc4948226msh1716c54bf80ad8dp1c8c12jsnac7a17a9e0a6'
            }
        };
        try {
            const res = await axios.request(options)
            setData(res.data)
        } catch (err) {
            console.error(err)
        }
    }

    // 早餐搜索副作用
    useEffect(() => {
        fetchFoodList(breakfastQuery, setBreakfastData)
    }, [breakfastQuery])

    // 午餐搜索副作用
    useEffect(() => {
        fetchFoodList(lunchQuery, setLunchData)
    }, [lunchQuery])

    // 晚餐搜索副作用
    useEffect(() => {
        fetchFoodList(dinnerQuery, setDinnerData)
    }, [dinnerQuery])

    // 零食搜索副作用
    useEffect(() => {
        fetchFoodList(snackQuery, setSnackData)
    }, [snackQuery])

    return (
        <div>
            <form class="w-full max-w-lg">
                {/* 早餐区域 */}
                <div class="flex flex-wrap -mx-3 mb-6">
                    <div class="w-full md:w-1/2 px-3 mb-6 md:mb-0">
                        <label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2" for="breakfast-input">
                            Breakfast
                        </label>
                        <input 
                            value={breakfastQuery} 
                            class="appearance-none block w-full bg-gray-200 text-gray-700 border border-red-500 rounded py-3 px-4 mb-3 leading-tight focus:outline-none focus:bg-white" 
                            id="breakfast-input" 
                            type="text" 
                            onChange={(e) => setBreakfastQuery(e.target.value)} 
                            placeholder="Search" 
                        />
                        {breakfastData?.hints?.map((item) => (
                            <div key={item.food.foodId || item.id}>
                                {item.food.label} 
                                <button>Add</button>
                            </div>
                        )) || 'No results found'}
                    </div>
                </div>
                {/* 午餐区域 */}
                <div class="flex flex-wrap -mx-3 mb-6">
                    <div class="w-full md:w-1/2 px-3">
                        <label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2" for="lunch-input">
                            Lunch
                        </label>
                        <input 
                            value={lunchQuery}
                            class="appearance-none block w-full bg-gray-200 text-gray-700 border border-gray-200 rounded py-3 px-4 leading-tight focus:outline-none focus:bg-white focus:border-gray-500" 
                            id="lunch-input" 
                            type="text" 
                            onChange={(e) => setLunchQuery(e.target.value)} 
                            placeholder="Search" 
                        />
                        {lunchData?.hints?.map((item) => (
                            <div key={item.food.foodId || item.id}>
                                {item.food.label} 
                                <button>Add</button>
                            </div>
                        )) || 'No results found'}
                    </div>
                </div>
                {/* 晚餐区域 */}
                <div class="flex flex-wrap -mx-3 mb-2">
                    <div class="w-full md:w-1/2 px-3">
                        <label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2" for="dinner-input">
                            Dinner
                        </label>
                        <input 
                            value={dinnerQuery}
                            class="appearance-none block w-full bg-gray-200 text-gray-700 border border-gray-200 rounded py-3 px-4 leading-tight focus:outline-none focus:bg-white focus:border-gray-500" 
                            id="dinner-input" 
                            type="text" 
                            onChange={(e) => setDinnerQuery(e.target.value)}
                            placeholder="Search" 
                        />
                        {dinnerData?.hints?.map((item) => (
                            <div key={item.food.foodId || item.id}>
                                {item.food.label} 
                                <button>Add</button>
                            </div>
                        )) || 'No results found'}
                    </div>
                </div>
                {/* 零食区域 */}
                <div class="flex flex-wrap -mx-3 mb-2">
                    <div class="w-full md:w-1/2 px-3">
                        <label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2" for="snack-input">
                            Snack
                        </label>
                        <input 
                            value={snackQuery}
                            class="appearance-none block w-full bg-gray-200 text-gray-700 border border-gray-200 rounded py-3 px-4 leading-tight focus:outline-none focus:bg-white focus:border-gray-500" 
                            id="snack-input" 
                            type="text" 
                            onChange={(e) => setSnackQuery(e.target.value)}
                            placeholder="Search" 
                        />
                        {snackData?.hints?.map((item) => (
                            <div key={item.food.foodId || item.id}>
                                {item.food.label} 
                                <button>Add</button>
                            </div>
                        )) || 'No results found'}
                    </div>
                </div>
            </form>
        </div>
    )
}

export default DietForm

优化建议

如果后续需要维护更多搜索区域,可把单个餐段的搜索逻辑封装为独立的MealSearch组件,每个组件内部维护自己的搜索词、结果集和请求逻辑,父组件仅需要传入餐段名称即可,可大幅减少重复代码。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 09:57:03