如何解决React Table 7.8.0动态更新数据时读取Redux旧状态问题
react-table v7 读取Redux旧状态问题修复
根因
react-table 7.8.0 版本对传入的数据源有强memoization校验要求,只会做引用对比,不会自动深度对比数据内容。你遇到的始终读取上一个Redux状态的问题,本质是组件重渲染时useTable没有拿到最新的data引用,和Redux数据流本身无关。
修复步骤
- 校验Redux侧更新逻辑
先确认reducer更新structuredEmi时遵守不可变数据规范:禁止直接修改原state上的structuredEmi属性(比如直接push、修改数组项属性),必须返回新的对象/数组引用,否则useSelector会判定值未变更,不会触发组件重渲染。
可以在父组件加临时日志校验:如果父组件打印的structuredEmi已经是最新值,问题出在表格组件内部;如果父组件拿到的就是旧值,先修正reducer的更新写法。// 错误的reducer写法(直接修改原state) state.structuredEmi.push(newItem) // 正确的reducer写法(返回新引用) return { ...state, structuredEmi: [...state.structuredEmi, newItem] } - 修正表格组件内部useTable的memo配置
这是该问题最高发的原因:useTable要求传入的columns、data必须用useMemo包裹,且依赖数组必须包含对应的props值,禁止给data/columns的useMemo传空依赖数组,漏写依赖会导致表格初始化后一直缓存第一次传入的旧数据,永远不会随props更新。
表格组件内部核心逻辑需按如下写法修正:import { useTable } from 'react-table' import { useMemo } from 'react' function IntrestBasisTable({ headerData, dataa }) { // columns必须加memo,依赖为传入的headerData const columns = useMemo(() => headerData, [headerData]) // data必须加memo,依赖为传入的dataa const data = useMemo(() => dataa, [dataa]) const tableInstance = useTable({ columns, data }) const { getTableProps, getTableBodyProps, headerGroups, rows, prepareRow } = tableInstance // 后续表格渲染逻辑保持原有实现即可 return (/* 表格JSX */) } - 排查父组件传参与渲染问题
首先修正父组件的渲染语法:你贴的代码里直接把structuredEmi写在JSX大括号内会被当成文本渲染到页面,正确的条件渲染写法为:
其次不要在给表格传props时临时构造新的数组/对象引用,比如不要写{structuredEmi && <IntrestBasisTable headerData dataa={structuredEmi}/>}dataa={structuredEmi.map(item => ({...item}))}这类每次渲染都会生成新引用的写法,直接传入从Redux拿到的原始structuredEmi即可,避免不必要的重渲染或状态错乱。
额外注意
如果表格内部存在编辑、排序等自定义操作,所有用到dataa的useCallback、useEffect都要把dataa加入依赖数组,避免闭包缓存旧值。
内容的提问来源于stack exchange,提问作者Rohit Rai
相关产品推荐
相关产品推荐

