先说结论
是闭包的原因导致我们的state数据在useEffect注入依赖后,打印的是最新值,而在onTableChange事件中打印获取的是闭包时的缓存值。
解决办法
引入useRef
去保存state,这样就能确保每次拿到的引用都是新的唯一的最新值。
代码示例:
// 编码模块
const Code = (props) => {
const {
searchParams, setSearchParams, selectedRowKeys, setSelectedRowKeys, tenantCode } = props;
// 创建newSearchParamsRef的目的是为了避免闭包导致影响获取最新数据,闭包会缓存上一次的数据
const newSearchParamsRef = useRef();
}
useLayoutEffect(() => {
codeFetchList(); // 更新table列表数据
newSearchParamsRef.current = {
...searchParams };
}, [searchParams, codeFetchList]);
// table onchange事件、排序
const handleTableChange = (pagination: any, filters: any, sorter: any) => {
const {
order, field } = sorter;
setSearchParams({
...(newSearchParamsRef.current || searchParams),
pageNo: 1,
});
};
<Table
sticky
rowKey={
(record: any) => record.id}
loading={
loading}
columns={
codeColumns}
dataSource={
codeList?.data?.rows}
onChange={
handleTableChange}
/>
)}
PS:类似的问题(原文链接:https://blog.csdn.net/weixin_44634727/article/details/122666435):
使用antd的table组件中渲染columns的时候无法正确获取到父组件的state问题
问题描述
首先我使用的是函数式组件(因为封装的原因,我将以下代码都写在了父组件函数里面)
然后在父组件中我定义了一个state,用于记录某个作用的id
初始值是333(这333后面有用)
但是在显示组件的时候,我利用useEffect函数,发起请求,获取后端最新的deptid,然后使用setDeptid对deptid进行从新的赋值
当重新赋值deptid之前,我是已经渲染 table的columns
下图是columns中的某一个操作列
如上图,删除按钮是一个deleteItem的函数
如图所示该函数执行会输出了父组件的state但是该输出却是1,并不是最新的数据
原因分析
究其原因发现原来,是我掉进了闭包陷阱当中
在渲染table的时候 我将之前的deptid放到了deleteItem中 由此形成了一个闭包 在内存中将之前的333缓存了起来 然后当你再次点击按钮触发deleteItem函数的时候 该值重新从缓存中拿出来 那么显示的就是之前的值,而在类组件中是不会存在这种问题的
解决方案
如上图所示 解决方案是在父组件中使用一个useRef钩子 来保存最新的数据 需要用的时候 直接console.log(countRef.current)即可