【问题标题】:Make only one row selectable at a time in React Table 7.1.0在 React Table 7.1.0 中一次只能选择一行
【发布时间】:2020-07-08 14:49:10
【问题描述】:

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

【问题讨论】:

  • 这一定是反应表问题吗?我只是使用项目 ID 对其使用一些组件级或全局状态管理。
  • @gazdagergo 我需要使用react table来渲染复选框,单击单选按钮时切换复选框选择,所以需要对react table进行这些操作,您能详细说明您的建议吗?我有点卡在这一点上..
  • 老实说,我不是 react table 的忠实粉丝。您可以非常轻松地设置复杂的表格,但是一旦您尝试添加自定义功能,就会浪费所有这些时间。这是我的经验。
  • @gazdagergo 是的,我同意,但是所有其他功能都已经与 react table 集成,只有这个尚未完成..所以现在这已经成为一个严重的问题.. 所以只是试图找到解决方案

标签: javascript reactjs radio-button react-table react-table-v7


【解决方案1】:

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

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

          return newState;
      },
    }
    ...

这里是CodeSandbox 描述的变化

【讨论】:

  • 这应该是正确的答案。
【解决方案2】:

使用 react-table 7.5.0,我有一个 put together a 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 的 Row Selection CodeSandbox,我是从这里分叉出来的。 Here's the relevant page in their docs.

稍后我会将代码移动到内置代码 sn-p 中。

【讨论】:

  • 非常有用!应该是公认的答案:)
【解决方案3】:

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

从表实例中获取 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) => (

【讨论】:

    【解决方案4】:
    Cell: ({row}) => (
       <IndeterminateCheckbox
          {...row.getToggleRowSelectedProps({
             onChange: () => {
               const selected = row.isSelected; // get selected status of current row.
               toggleAllRowsSelected(false); // deselect all.
               row.toggleRowSelected(!selected); // reverse selected status of current row.
             },
          })}
       />
    )
    

    【讨论】:

      【解决方案5】:

      这是使用useReducer 对“radio-like”行为进行简单的 react 实现,以演示如何将状态管理与 table 一起使用。

      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>

      【讨论】:

        【解决方案6】:

        您还可以覆盖 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'
        

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

        【讨论】:

          猜你喜欢
          • 2017-05-02
          • 2019-10-11
          • 2017-06-28
          • 2011-01-26
          • 1970-01-01
          • 2021-06-17
          • 2020-07-26
          • 2023-03-20
          • 1970-01-01
          相关资源
          最近更新 更多