React中下拉选择onChange与useEffect配合的过滤显示问题排查
问题根源分析
- 不使用useEffect时的问题:
setPriceValue是异步更新状态的操作,在handlePriceChange里刚调用setPriceValue就用priceValue过滤数据,此时priceValue还是更新前的旧值(初始为空字符串),所以第一次选择时过滤逻辑用的是空值,不会改变数据;第二次选择时,priceValue已经是第一次选择的值,过滤才生效。 - 使用useEffect时的问题:初始渲染时
priceValue是空字符串,useEffect会执行handlePriceChange,但此时没有合法的event参数,而且过滤逻辑会用空值匹配,导致houses变成空数组,所以页面初始为空。
修复方案
我们需要把状态更新和过滤逻辑解耦,利用useEffect监听priceValue的变化,根据当前值过滤数据,同时保证初始状态下展示所有数据。
修复后的代码:
import { useEffect, useState } from "react"; import data from "./data"; const SearchBar = () => { const [houses, setHouses] = useState(data); const [loading, setLoading] = useState(true); const [priceValue, setPriceValue] = useState("select"); // 仅负责更新选中的价格值 const handlePriceChange = (event) => { setPriceValue(event.target.value); }; // 监听价格值变化,执行过滤逻辑 useEffect(() => { if (priceValue === "select") { // 选择默认选项时,展示所有数据 setHouses(data); } else { // 根据选中的价格过滤数据 const filteredHouses = data.filter(house => house.price === priceValue); setHouses(filteredHouses); } }, [priceValue]); // 初始化完成后关闭加载状态 useEffect(() => { setLoading(false); }, []); return ( <> <div className="search-bar" id="search"> <label className="price-label"> Price <select value={priceValue} onChange={handlePriceChange} className="dropdown-menu" > <option value="select">Select</option> <option value="$250-350K">$250-350K</option> <option value="$350-550K">$350-550K</option> <option value="$550-750K">$550-750K</option> </select> </label> </div> <div className="lower-section" id="houses"> {loading ? ( <div>Loading...</div> ) : ( houses.map((house) => { const { id, pictureURL } = house; return ( <div key={id} className="house-div"> <img src={pictureURL} alt="house" /> <button className="btn-more">Show details</button> </div> ); }) )} </div> </> ); }; export default SearchBar;
关键修改点
- 拆分
handlePriceChange:只负责更新priceValue状态,避免异步状态更新导致的旧值误用问题。 - 用
useEffect监听priceValue:每次值变化时,根据当前选中的价格过滤数据;选择默认的"Select"选项时,重置为全部数据,保证初始展示所有内容。 - 优化初始状态:把
priceValue的初始值设为"select",和下拉默认选项对应,逻辑更统一。
内容的提问来源于stack exchange,提问作者Al Si
相关产品推荐
相关产品推荐

