React自定义过滤hook useFilterData首次渲染返回空列表问题求助
问题根源
- useState初始值仅在Hook首次挂载时生效:首次调用
useFilterData时,你的data大概率还未加载完成(比如是异步接口返回数据),初始值为空数组,因此filteredList被初始化为空。后续data加载完成更新后,useState不会重新读取初始值,且你原有逻辑中useEffect仅监听searchValue,不会触发重新过滤,直到修改搜索值后才会拿到最新data计算结果。 - 监听data触发无限循环的原因:你传入的
data、keyList每次渲染都会生成新的引用(比如组件内每次渲染都重新生成数组、异步返回数据未做引用稳定处理),useEffect依赖浅对比每次都判定依赖更新,触发setState后又引发重渲染,形成死循环。 - 补充日志的异常也符合上述逻辑:首次log是data更新后重渲染时打印的已加载完成数据,但useState初始值已经在挂载阶段读取了当时的空数组,因此后续打印的
filteredList始终为空。
解决方案
最优方案:用useMemo重构Hook(无状态同步问题,无无限循环风险)
过滤逻辑本身是输入参数的纯计算行为,无需用useState存储结果,直接用useMemo缓存计算结果即可,天然解决首次渲染不同步的问题:
import React from 'react' import { matchSorter } from 'match-sorter' const useFilterData = (searchValue, keyList, data) => { const filteredList = React.useMemo(() => { if (!searchValue) return data return matchSorter(data, searchValue, { keys: keyList, }) }, [searchValue, keyList, data]) return [filteredList] } export default useFilterData
组件侧配合稳定引用
组件内生成的columnKeys默认每次渲染都是新数组,需要用useMemo稳定引用,避免不必要的重复计算:
// data如果是异步接口返回,请存储在useState中,保证仅数据实际变化时才更新引用 const data = [{}, {}, {}] const columns = [{'field': 'one'}, {'field': 'two'}, {'field': 'three'}] // 用useMemo稳定columnKeys引用,仅columns变化时才重新生成 const columnKeys = React.useMemo(() => columns.map((c) => c.field), [columns]) const [searchValue, setSearchValue] = React.useState('') const [filteredList] = useFilterData( searchValue, columnKeys, data, ) return ( <div> <Paper> {/* 补充value属性变为受控组件,避免输入异常 */} <TextField onChange={(e) => setSearchValue(e.target.value)} value={searchValue} /> <DataGrid rows={filteredList} columns={columns} /> </Paper> </div> ) }
内容的提问来源于stack exchange,提问作者watermelon_party
相关产品推荐
相关产品推荐

