title: [ISSUE-0010] 拖动表格列宽后被自动重置 description: "字段拖动宽度会被自动重置" tags: [issue] created: 2026-05-26 updated: 2026-05-26 type: issue status: fixed severity: medium
[ISSUE-0010] 拖动表格列宽后被自动重置¶
相关源码:
src/sections/page/local-table.tsx
用户感知的现象¶
"字段拖动宽度会被自动重置"
用户拖动表格列宽 → 松手时变化生效 → 但数据 fetch / 刷新后列宽又回到默认值。
根因分析¶
实际查源码发现有 2 个 bug:
Bug 1:stale closure(use-table-columns-config.tsx:21)¶
const updateWidth = (field, width) => {
setColumnsWidth({ ...columnsWidth, [field]: width }); // closure 旧值
};
闭包捕获的是上一次 render 的 columnsWidth。React 18 自动 batch 下,连续拖动用旧值覆盖前一次写入,部分宽度会丢。
Bug 2:columns 数组引用每次 render 都变(client-data-table.tsx:131)¶
const renderColumns = () => { ... return newColumns; };
// 调用处
<DataGridPremium columns={renderColumns()} ... />
每次 render 返回新数组 → DataGridPremium 看到 columns prop 引用变化 → 内部 width state 重置 → 用户拖动后下次 render 就回到 columns prop 里写的值(这个值是 closure 旧值,所以又错)。
两个 bug 互相放大,结果就是「拖完立即被重置」。
修复方案¶
// 1. useTableColumnsConfig.tsx — functional setState 修 closure
const updateWidth = (field, width) => {
setColumnsWidth((prev) => ({ ...(prev || {}), [field]: width }));
};
// 2. client-data-table.tsx — useMemo 缓存 columns 引用
const memoColumns = useMemo(() => { ... }, [columnsList, columnsWidth, defaultColumns]);
const renderColumns = () => memoColumns;
改动文件¶
| 文件 | 改了什么 |
|---|---|
src/hooks/cache/use-table-columns-config.tsx |
updateWidth 改 functional setState |
src/components/table/client-data-table.tsx |
renderColumns 用 useMemo 缓存 |
验证方式¶
- 拖动「商家」列宽 → 100px
- 切换 chip 触发刷新 → 列宽应保持 100px
- 关闭主面板再打开 → 列宽应仍 100px
- 测多个列同时调
如何避免再犯¶
- 任何"用户调整的 UI 状态"必须持久化(列宽 / 排序 / 折叠 / 选项)
- 数据 fetch 时不要重置 UI state,只 setState data 而不 setColumns
相关问题¶
- 无