Material UI Autocomplete搜索后重渲染及异步dispatch优化咨询
解决方案
1. 绑定输入值状态,解决失焦清空问题
给组件加个状态控制Autocomplete的输入值,避免失焦时自动清空:
const [inputVal, setInputVal] = useState('');
然后给Autocomplete补上inputValue和onInputChange属性,同时修正renderInput里的TextField参数传递错误:
<AutoCompleteNewDesign // 保留原有其他属性 disableClearable freeSolo id="combo-box-demo" onChange={(e, selectValue) => { setInvoiceSelectedData(selectValue); }} options={invoiceSearchList} getOptionLabel={option => (option ? String(option?.data1) : '')} renderOption={option => ( <div> {option.data1} - {option.data2} </div> )} inputValue={inputVal} onInputChange={(e, newInputValue) => { setInputVal(newInputValue); debouncedSearch(newInputValue); }} renderInput={params => ( <TextField {...params} // 必须展开params,而非直接传params={params} name="name-here" variant="outlined" /> )} filterOptions={filterOptions} />
注意:移除原来renderInput里的onChange,统一移到onInputChange中处理。
2. 给异步dispatch加防抖,减少不必要的重渲染
频繁触发dispatch会导致多次请求和组件重渲染,用防抖函数限制请求频率:
// 可使用lodash的debounce,或自行实现简单防抖逻辑 import { debounce } from 'lodash'; const debouncedSearch = useCallback( debounce((value) => { if (value.trim()) { dispatch(searchName(value)); } else { // 可选:输入为空时清空搜索结果 dispatch(clearSearchResults()); } }, 300), // 300ms防抖间隔,可按需调整 [dispatch] ); // 组件卸载时取消防抖定时器,避免内存泄漏 useEffect(() => { return () => debouncedSearch.cancel(); }, [debouncedSearch]);
3. 优化useSelector,避免无意义重渲染
默认useSelector会做严格比较,只要state有变化就触发组件重渲染,通过以下方式优化:
// 方法1:用shallowEqual做浅比较 import { shallowEqual, useSelector } from 'react-redux'; const { searchedNames } = useSelector( state => state.searchReducer, shallowEqual ); // 方法2:用reselect的createSelector缓存结果(需安装reselect) import { createSelector } from 'reselect'; import { useSelector } from 'react-redux'; const selectSearchReducer = state => state.searchReducer; const selectSearchedNames = createSelector( [selectSearchReducer], searchReducer => searchReducer.searchedNames ); const searchedNames = useSelector(selectSearchedNames);
4. 缓存options数组,稳定组件渲染
如果invoiceSearchList基于searchedNames生成,用useMemo缓存数组,避免每次渲染生成新数组导致Autocomplete重渲染:
const invoiceSearchList = useMemo(() => { return searchedNames || []; // 按实际数据结构调整 }, [searchedNames]);
内容的提问来源于stack exchange,提问作者nekromenzer
相关产品推荐
相关产品推荐

