2

我正在尝试用一次只能选择一行来实现反应表。我已经经历了很多在反应表中选择多行的示例,但在我的情况下,当用户单击单选按钮时,用户只能选择一行,但目前可以选择所有行。任何人都可以帮我解决这个问题吗?

在此处输入图像描述

4

5 回答 5

4

使用 react-table 7.5.0,我将 CodeSandbox与 react-table 放在一起,在功能上一次只能选择一行。

本质上,我替换了一个无条件渲染的复选框:

Cell: ({ row }) => (
  <div>
    <IndeterminateCheckbox {...row.getToggleRowSelectedProps()} />
  </div>
)

带有条件渲染的复选框:

Cell: ({ row }) => {
  if (
    rows.filter((row) => row.isSelected).length < 1 ||
    row.isSelected
  ) {
    return (
      <div>
        <IndeterminateCheckbox {...row.getToggleRowSelectedProps()} />
      </div>
    );
  } else {
    return (
      <div>
        <IndeterminateCheckbox
          checked={false}
          readOnly
          style={row.getToggleRowSelectedProps().style}
        />
      </div>
    );
  }
}

我过滤了所有行对象以检查所选行,然后如果所选行数小于 1 或该行已被选中,则有条件地呈现一个正常运行的反应表复选框。

如果选中的行数至少为 1 并且未选中该行,我会呈现一个无法选中的只读复选框。

理想情况下,我希望使用 react-table 的内置selectedRowIds而不是过滤所有行对象,但我无法弄清楚如何以允许我引用它的方式实现 useTable(),因为它是派生的从中。

这是我派生出来 的 react-table 的行选择代码沙箱。这是他们文档中的相关页面

稍后我会将代码移动到内置代码片段中。

于 2020-08-19T23:10:05.800 回答
4

我知道这是一个老问题,但也许有人会发现这个解决方案很有用。从版本 7 开始,react-table 提供了一个stateReducer可用于跟踪和更改表状态的方法。(在 v7 之前它有reducerHandlers,但我没有深入探讨)。您可以按如下方式修改状态:

useTable(
    {
      columns,
      data,
      stateReducer: (newState, action) => {
          if (action.type === "toggleRowSelected") {
            newState.selectedRowIds = {
              [action.id]: true
            }
          }

          return newState;
      },
    }
    ...

这是带有描述的更改的CodeSandbox

于 2021-07-06T17:47:42.723 回答
0

您还可以覆盖 Cell(...) 道具函数上的 onChange 方法。

https://react-table.tanstack.com/docs/api/useRowSelect#row-properties

getToggleRowSelectedProps: Function(props) => props
Use this function to get the props needed for a select row checkbox.
Props:
onChange: Function()
style.cursor: 'pointer'
checked: Bool
title: 'Toggle Row Selected'

等我有空的时候再给个沙盒。

于 2020-10-01T16:38:33.127 回答
0

这是一个旧的,但这是我的解决方案:

从表实例中获取toggleAllRowsSelected 。

  const {
    allColumns,
    getTableBodyProps,
    getTableProps,
    headerGroups,
    prepareRow,
    rows,
    state,
    toggleAllRowsSelected,
  } = useTable(
    {
      columns,
      data,
    },
    useRowSelect
  );

然后像下面的代码一样将onClick添加到您的tr组件中(在我的代码中,tr已用情感设置样式并命名为StyledTableRow)。这将首先将所有选定的行设置为 false,然后切换当前行的isSelected值,如果它最初是false,如果它是true ,那么它已经被设置为 false。

如果您不想允许单击选定的行来取消选择它(例如,对于单选按钮),只需使用isSelected === true来阻止此处的任何操作。

{rows.map((row, i) => {
            prepareRow(row);
            // const isRowSelected = isSelected(row.id);
            const { isSelected, getRowProps, getToggleRowSelectedProps, toggleRowSelected } = row;
            const {
              onChange,
              indeterminate,
              ...toggleRowSelectedProps
            } = getToggleRowSelectedProps();
            console.log(row);
            return (
              <StyledTableRow
                hover
                {...getRowProps()}
                {...toggleRowSelectedProps}
                selected={isSelected}
                onClick={() => {
                  const current = isSelected;
                  toggleAllRowsSelected(false);
                  if (!current) {
                    toggleRowSelected();
                  }
                }}
              >
                {row.cells.map((cell, key) => (
于 2022-02-10T11:50:40.230 回答
0

这是“无线电式”行为的简单反应实现,useReducer用于演示如何使用表的状态管理。

const { useReducer } = React; // --> for inline use
// import React, { useReducer } from 'react';  // --> for real project


const reducer = (state, action) => {
  return { checkedId: action.id }
}

const App = () => {
  const [state, dispatch] = useReducer(reducer, {})
  
  const CheckBox = ({id}) => (
    <input
      id={id}
      onClick={() => dispatch({ id })}
      checked={state.checkedId === id}
      type="checkbox"
    />
  )

 
  return (
    <table border="1">
      <tr><td><CheckBox id="1" /></td><td>John</td></tr>
      <tr><td><CheckBox id="2" /></td><td>Doe</td></tr>
    </table>
  )
};


ReactDOM.render(<App />, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.9.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.9.0/umd/react-dom.production.min.js"></script>
<div id="root"></div>

于 2020-07-09T08:37:52.060 回答