React组件渲染状态初始化问题:filteredList未同步resDataList
问题原因与解决方案
核心误区
你对useState的初始化逻辑理解有误:useState的初始值参数只在组件第一次渲染时生效,后续组件重新渲染时,这个参数会被直接忽略,不会自动用新的resDataList去更新filteredList。所以当resDataList从空数组加载出数据后,filteredList还是保持第一次初始化的空数组,自然不会渲染内容。
修复步骤
- 添加
useEffect监听resDataList变化
在Body组件里新增一个useEffect,当resDataList加载完成(长度不为0)时,将其赋值给filteredList:
import { useState, useEffect } from 'react'; export const Body = () => { const resDataList = useResData(); const [filteredList, setFilteredList] = useState([]); const [inputText, setInputText] = useState(''); // 监听resDataList变化,更新filteredList初始值 useEffect(() => { if (resDataList.length > 0) { setFilteredList(resDataList); } }, [resDataList]); const filterList = () => { let filtered = resDataList.filter((item) => item.info.avgRating > 4); setFilteredList(filtered); } if (resDataList.length === 0) return <Shimmer />; return ( <div className="Body"> <div className="search"> <input className="search-input" value={inputText} onChange={(e) => setInputText(e.target.value)} /> <button className="search-btn" onClick={() => { let list = resDataList.filter((data) => data.info.name.toLowerCase().includes(inputText.toLowerCase()) ); setFilteredList(list); }} > Search </button> </div> <div className="filter-btn"> <button onClick={filterList}>Top Rated Restaurants</button> </div> <div className="cardContainer"> {filteredList.map((item) => <Link to={`restaurants/${item.info.id}`} key={item.info.id} > <Card resData={item?.info} /> </Link> )} </div> </div> ) }
- 修复自定义钩子的语法问题
原useResData里的getData声明存在语法错误,同时增加错误处理和默认值兜底:
import { useState, useEffect } from 'react'; const useResData = () => { const [resDataList, setResDataList] = useState([]); useEffect(() => { // 正确声明async函数 const getData = async () => { try { let res = await fetch( "https://www.swiggy.com/dapi/restaurants/list/v5?lat=28.65200&lng=77.16630&is-seo-homepage-enabled=true&page_type=DESKTOP_WEB_LISTING" ); let data = await res.json(); // 兜底空数组,避免API结构变化导致undefined setResDataList(data?.data?.cards?.[4]?.card?.card?.gridElements?.infoWithStyle?.restaurants || []); } catch (err) { console.error('数据获取失败:', err); setResDataList([]); } } getData(); }, []) return resDataList; } export default useResData;
额外优化点
- 搜索逻辑中把
inputText转成小写,避免大小写不匹配导致的搜索失效 - 给
setResDataList添加默认空数组,防止API返回结构变化时出现异常 - 给fetch请求增加错误捕获,避免请求失败导致组件崩溃
内容的提问来源于stack exchange,提问作者meg
相关产品推荐
相关产品推荐

