过滤数据时出现Maximum update深度超限警告的原因及排查
解决React组件无限渲染警告问题
问题原因
出现Maximum update depth exceeded警告的核心原因有两个:
- 衍生数据用state存储触发循环渲染:你通过
useEffect监听valueInput和data,调用setFilteredDataList更新状态会触发组件重渲染;而selectFromResult中每次都会生成新数组([...new Set(modifiedData)]),导致data的引用每次渲染都变化,进而再次触发useEffect,形成循环。 - query参数可能存在错误:
useGetTableDataQuery中使用了${value ?? ''},但代码里定义的状态是checkedFilterValues,如果value未定义或频繁变化,会导致queryKey不断改变,重复发起请求,加剧循环。
修复方案
1. 用useMemo替代useEffect+state计算衍生数据
filteredDataList是基于data和valueInput的衍生数据,无需单独存为state,直接用useMemo计算即可避免不必要的状态更新:
const [valueInput, setValueInput] = useState('') const [checkedFilterValues, setCheckedFilterValues] = useState() const { isLoading, error, data } = useGetTableDataQuery( // 修正query参数,替换为定义好的checkedFilterValues `${url}?${column.id}=${checkedFilterValues ?? ''}`, { selectFromResult: ({ data, ...rest }) => { if (!data || !data.data) { return { data: [], ...rest } } // 用useMemo缓存去重数组,避免每次生成新引用 const removedDuplicatesData = useMemo(() => { const modifiedData = data.data.map(item => item[column.id]) || [] return [...new Set(modifiedData)] }, [data.data, column.id]) return { data: removedDuplicatesData, ...rest } }, } ) // 直接用useMemo计算过滤后的数据 const filteredDataList = useMemo(() => { if (!data || data.length === 0 || isLoading) return [] if (!valueInput) return data return data.filter(listItem => listItem.toLowerCase().includes(valueInput.toLowerCase()) ) }, [valueInput, data, isLoading])
2. 确保query参数稳定
如果checkedFilterValues需要频繁更新,可添加防抖处理,避免短时间内重复发起API请求,减少数据更新带来的渲染触发。
3. 缓存去重数组优化
在selectFromResult中用useMemo缓存去重后的数组,只有当data.data或column.id变化时才重新生成,保证data的引用仅在内容变化时更新,减少无意义的依赖触发。
修复逻辑说明
- 用
useMemo计算衍生数据,不会触发setState,避免组件额外重渲染。 - 缓存去重数组,确保
data引用稳定,防止useMemo被无意义触发。 - 修正query参数错误,避免不必要的API请求,切断循环渲染的触发源。
内容的提问来源于stack exchange,提问作者David Abramov
相关产品推荐
相关产品推荐

