Ant Design Table列定义中render函数为何会重复执行两次
Ant Design Table 中 render 函数重复执行的原因
核心触发逻辑
- React 开发环境的内置校验规则
只要项目在入口文件用了React.StrictMode包裹根组件,开发模式下React就会强制把所有组件的渲染流程跑两遍,专门用来排查渲染过程中违规的副作用操作。这种场景下,只要是在渲染链路里执行的函数(包括Table列配置里的render方法),都会被触发两次。这是开发环境专属的校验逻辑,生产打包后双重执行的行为会自动消失,不属于代码bug。 - 当前代码写法导致的无意义全量重渲染
现在的columns数组是直接写在ModalMore组件的函数体内部的,这意味着只要组件因为任何原因重渲染一次,整个columns数组都会被重新创建,里面每个render函数的引用也会跟着变。
Ant Design的Table内部对传入的columns、dataSource做了浅比较优化,只要检测到columns的引用变了,就会把所有列的单元格渲染逻辑全部重跑一遍——哪怕dataSource一条数据都没改,只要columns是新生成的对象,render就会全量重新执行。 - 再叠加Modal组件的特性:Modal在打开、关闭的动画流转过程中,本身就会触发多次自身及内部子组件的重渲染,进一步让render的执行次数翻倍。
验证与优化方案
- 快速确认StrictMode的影响:临时把入口文件里的
React.StrictMode标签去掉,重新跑项目后看控制台console.log(33)的打印次数,如果直接少了一半,就说明近一半的重复执行是开发环境校验逻辑带来的。 - 减少不必要的全量重渲染:
- 如果columns配置完全不依赖组件内部的动态状态,直接把columns的定义移到组件外面,避免组件每次重渲染都重新生成配置对象;
- 如果columns需要根据组件内部的状态动态生成,就用
useMemo给columns做缓存,只有依赖项变化的时候才重新生成列配置:const columns = useMemo(() => [ { title: 'Name', dataIndex: 'name', key: 'name' }, { title: 'Age', dataIndex: 'age', key: 'age' }, { title: 'Address', key: 'address' }, { title: 'Action', dataIndex: '', key: 'x', render: (text, record) => { console.log(33) return <span onClick={(e) => onDelete(record.key, e)}>Delete</span> } } ], [/* 填入columns实际依赖的内部状态变量 */])
- 实际开发注意:如果render函数只做纯UI渲染,没有写发请求、改全局变量这类带副作用的逻辑,哪怕多跑几次,也不会影响最终页面效果,不需要为了减少控制台日志做过度优化。但如果在render里写了副作用逻辑,不管跑几次都是代码隐患,应该把这些逻辑移到对应的事件回调、生命周期函数里,不要直接写在render方法中。
内容的提问来源于stack exchange,提问作者Стас Рябцев
相关产品推荐
相关产品推荐

