简体   繁体   English

Checkbox由Z9ED39E2EA2EA931586B6A985A6942EF573EZ驱动到检查时没有响应Onchange

[英]Checkbox doesn't respond to onChange when checked is driven by state

I have a material-ui Table and have been implementing multi-select functionality on it.我有一个 material-ui Table ,并且一直在上面实现多选功能。

My multi select should behave as follows:我的多 select 应该表现如下:

  • Select checkboxes only appear at the start of a row on hover (when nothing has been selected) Select 复选框仅出现在 hover 的行首(未选择任何内容时)
  • Once one row has been selected, all other checkboxes become permanently visible.一旦选择了一行,所有其他复选框将永久可见。
  • The checkbox in the TableHead will select / deselect all rows in the Table when toggled. TableHead 中的复选框将在切换时TableHead / 取消选择Table中的所有行。

Each row has its own individual unique id .每行都有自己独特的id

I maintain a Set called idsOfSelectedRows via a useState hook to keep track of all rows currently selected.我通过一个useState挂钩维护一个名为idsOfSelectedRowsSet ,以跟踪当前选择的所有行。

Each TableRow has a Checkbox which looks like this每个TableRow都有一个Checkbox ,看起来像这样

<Checkbox
  className={
     idsOfSelectedRows.size === 0 &&
     styles.rowSelectionCheckboxStyle
  }
  onChange={() => handleRowSelectionCheckboxClick}
  checked={idsOfSelectedRows.has(row.id)}
 />

and handleRowSelectionCheckboxClick looks like thishandleRowSelectionCheckboxClick看起来像这样

  const handleRowSelectionCheckboxClick = event => {
    const idOfClickedRow = event.target.attributes.getNamedItem("id").value;
   //If the checkbox has just become checked then add it to the idOfSelectedRows Set, otherwise remove it.
    setIdsOfSelectedRows(
      event.target.checked
        ? new Set(idsOfSelectedRows.add(String(idOfClickedRow)))
        : () => {
            idsOfSelectedRows.delete(String(idOfClickedRow));
            return new Set(idsOfSelectedRows);
          }
    );
  };

My issue is that clicking on the checkboxes on the rows is unresponsive.我的问题是单击行上的复选框没有响应。 I can select them all by clicking on the select all Checkbox in the TableHead but clicking on checkboxes in individual rows does not change their state?我可以通过单击表头中的select 所有CheckboxTableHead所有这些复选框,但单击各个行中的复选框不会更改其 state?

Here's a full CodeSandbox reproducing the exact issue.这是重现确切问题的完整 CodeSandbox。 What do I need to do to make the checkboxes in the rows be toggleable?我需要做什么才能使行中的复选框可切换?

编辑悬停表行复选框

Remove the () => from the onChange assignment for a quick fix.onChange分配中删除() =>以便快速修复。

Why为什么

You're declaring an anonymous inline function, but that function does not call anything (missing () that is syntax to call a function).您正在声明一个匿名内联 function,但 function 没有调用任何东西(缺少()是调用函数的语法)。 onChange accepts a function reference. onChange接受 function 参考。 When you give it an inline function, that's the function it will call.当你给它一个内联 function 时,它会调用 function。 The other option is to only pass it the function reference of handleRowSelectionCheckboxClick , and then that function will be called on change instead of the anonymous function middleman.另一种选择是仅将句柄RowSelectionCheckboxClick 的handleRowSelectionCheckboxClick引用传递给它,然后在更改时将调用 function 而不是匿名的 ZC1C425268E68385D14AB5074C17Z9 中间人。

So your two options are:所以你的两个选择是:

onChange={handleRowSelectionCheckboxClick} // Just the reference

OR或者

onChange={(e) => handleRowSelectionCheckboxClick(e)} // New inline function that calls your function 

The second way is unnecessary in most cases.在大多数情况下,第二种方式是不必要的。 The first is preferred unless you need to pass custom parameters.除非您需要传递自定义参数,否则首选第一个。 Here is an example of how it might be useful:以下是它可能有用的示例:

onChange={(e) => handleRowSelectionCheckboxClick(e, id)}

In your sandbox, you map over elements and each gets a change handler.在您的沙箱中,您对元素进行 map 并且每个元素都获得一个更改处理程序。 To treat them separately in the handler, you can pass an extra variable to the function like above.要在处理程序中单独处理它们,您可以像上面一样将一个额外的变量传递给 function。

For example, I got your sandbox working by changing the handler and assignment to this:例如,我通过将处理程序和分配更改为:

const handleRowSelectionCheckboxClick = (event, idOfClickedRow) => {

...

onChange={(e) => handleRowSelectionCheckboxClick(e, row.id)}

This line: event.target.attributes.getNamedItem("id").value;这一行: event.target.attributes.getNamedItem("id").value; won't give you the required id, since there isn't one passed, change the chekbox like so:不会为您提供所需的 id,因为没有通过,请像这样更改chekbox

<Checkbox
    id={row.id}
    onChange={handleRowSelectionCheckboxClick}
    checked={idsOfSelectedRows.has(row.id)}
/>

Then, retreive the ID like so:然后,像这样检索 ID:

const idOfClickedRow = event.target.attributes.id.value;

Updated codesandbox : 更新的代码框

编辑悬停表行复选框


Like the other answers suggest, change the handleRowSelectionCheckboxClick function call like shown in the example. 像其他答案建议的那样,更改handleRowSelectionCheckboxClick function 调用,如示例中所示。 If you like your solution with an anonymous function, you should add the () : onChange={() => handleRowSelectionCheckboxClick()} 如果您喜欢匿名 function 的解决方案,您应该添加()onChange={() => handleRowSelectionCheckboxClick()}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM