Skip to content

Bulk delete / by-name bulk action clears the toolbar but leaves the row checkboxes ticked #3056

Description

@os-zhuang

ObjectGrid 的两套选择状态在 dispatchBulkAction 这条路径上会脱钩:工具栏消失了,行复选框还全勾着。

现状

选择状态有两个来源,必须同步移动:

  • selectedRows(ObjectGrid 自己的 state)—— 驱动 BulkActionBar("已选择 N 项" + 清除)
  • data-table 内部的 selectedRowIds —— 驱动行复选框,只有宿主 bump selectionResetKey 时才清空(data-table.tsx:586

富 def 那条路走 handleBulkDialogClose,两个都清:

// ObjectGrid.tsx:1797
if (result && result.succeeded > 0) {
  setSelectedRows([]);
  setSelectAllMatching(false);
  setSelectionResetKey(k => k + 1);   // ← 行复选框
  setRefreshKey(k => k + 1);
}

dispatchBulkAction两条分支都漏了最后那半

// ObjectGrid.tsx:1717 —— 内建/声明的批量删除
if (action === 'delete' && onBulkDelete) {
  onBulkDelete(expanded);
  setSelectedRows([]);
  setSelectAllMatching(false);        // ← 没有 setSelectionResetKey
  return;
}
// ObjectGrid.tsx:1729 —— 按名字派发(消费方注册的 runner handler)
if (res?.success) {
  setSelectedRows([]);
  setSelectAllMatching(false);        // ← 同样没有
  setRefreshKey(k => k + 1);
}

于是操作成功后:工具栏消失(selectedRows 空了),但每行复选框仍然是勾选态。用户看到的是「一堆勾着的行 + 没有任何批量操作入口」,只能手动逐个取消或刷新页面。

有意思的是,handleBulkDialogClose 的注释逐字点名了这个失败模式,只是另一条路径没有遵守:

Both selection sources must move together, or the checkboxes (table-internal) and the toolbar (our selectedRows) drift out of sync — ticked rows with no toolbar.

影响面

不是回归 —— dispatchBulkAction 一直如此。#3031 / #3053 之后这条路径变窄了(能解析到对象 action 的名字现在会被提升成 def,走对话框那条正确的路),剩下两种情况仍然命中:

  1. 批量删除 —— 内建的 ['delete'] 兜底,或作者显式写的 bulkActions: ['delete']。这是最常见的一条。
  2. 按名字派发 —— 消费方用 runner.registerHandler('<name>', …) 注册过、且对象没有同名 action 声明的批量操作。

建议

把两条分支都补上 setSelectionResetKey(k => k + 1),和 handleBulkDialogClose 对齐。删除分支是无条件成功语义(onBulkDelete 不回传结果),按名字那条已经在 res?.success 里了,位置现成。

值得顺手加一条断言把这个不变量钉住 —— bulkActionRefresh.test.tsx 里已经有一组同类测试("clears the row checkboxes (not just the toolbar) after a successful run"),针对的正是富 def 那条路径,照着扩到字符串/删除路径即可。

发现于 #3002 的浏览器验证过程中。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions