Material UI Autocomplete防抖功能异常问题求助
解决Material UI Autocomplete防抖失效问题
你的代码问题出在闭包捕获旧状态以及防抖函数的使用方式上,导致每次输入都触发请求,且无法获取最新的输入值。以下是具体问题和修复方案:
核心问题
- 闭包捕获旧值:
loadData直接引用组件内的inputValue状态,而debouncedLoadData通过useCallback创建时依赖为空数组,它捕获的是组件首次渲染时的loadData,这个函数里的inputValue永远是初始的空字符串。后续输入更新状态后,防抖函数执行时仍使用旧值,导致过滤逻辑错误。 - 防抖未正确传递最新输入值:你在
handleInputChange中先调用setInputValue(v)(异步更新状态),再调用debouncedLoadData,此时inputValue尚未更新,防抖函数拿到的还是更新前的值。
修复代码
import { useState, useCallback, useEffect } from "react"; import { Autocomplete, TextField } from "@mui/material"; import { debounce } from "lodash"; import topFilms from "./topFilms"; export default function App() { const [value, setValue] = useState(null); const [inputValue, setInputValue] = useState(""); const [options, setOptions] = useState([]); // 让loadData接收输入值作为参数,不再依赖闭包的inputValue const loadData = (searchValue) => { const filteredOptions = topFilms.filter((f) => f.title.includes(searchValue) ); console.log( `loadData with ${filteredOptions.length} options based on "${searchValue}"` ); setOptions(filteredOptions); }; // 创建防抖函数,接收参数并传递给loadData const debouncedLoadData = useCallback( debounce((searchValue) => { loadData(searchValue); }, 1000), [] ); const handleInputChange = (e, v) => { setInputValue(v); // 直接传递最新的输入值v给防抖函数 debouncedLoadData(v); }; const handleChange = (e, v) => { setValue(v); }; // 组件卸载时取消防抖,避免内存泄漏 useEffect(() => { return () => { debouncedLoadData.cancel(); }; }, [debouncedLoadData]); return ( <div className="App"> <Autocomplete value={value} inputValue={inputValue} onChange={handleChange} onInputChange={handleInputChange} disablePortal options={options} getOptionLabel={(option) => option.title} isOptionEqualToValue={(option, value) => option.title === value.title} id="combo-box-demo" renderInput={(params) => <TextField {...params} label="Movie" />} /> </div> ); }
关键改动说明
- 传递输入值参数:将
loadData修改为接收searchValue参数,调用防抖函数时直接传入最新的输入值v,彻底避免闭包捕获旧状态的问题。 - 防抖函数封装:在
debounce内部直接调用loadData并传递参数,确保每次触发都使用最新的输入值。 - 组件卸载清理:添加
useEffect在组件卸载时调用debouncedLoadData.cancel(),防止防抖函数在组件卸载后仍执行,造成内存泄漏。
内容的提问来源于stack exchange,提问作者ton1
相关产品推荐
相关产品推荐

