从较高的组件中取消选择所有行

deselecting all rows from higher component

提问人:dmikester1 提问时间:10/3/2023 最后编辑:terahertzdmikester1 更新时间:10/8/2023 访问量:125

问:

我正在将 React Table v8 用于我的新 Web 应用程序。我有一个表格,上面有用于选择行的复选框。在组件树中较高位置的组件中,我正在对选定的行执行某些操作,然后我想清除所有选定的行。我在搜索时发现了函数 toggleAllRowsSelected。我尝试将这个“useEffect”添加到我的表组件中。

useEffect(() => {
    if (selectedRows.length === 0) {
        table.toggleAllRowsSelected(false);
    }
}, [selectedRows]);

然后,我从组件树中的组件向上传递了“selectedRows”。 但这会导致连续的运行循环。

我正在像这样创建我的 ReactTable:

const table = useReactTable({
    data,
    columns,
    state: {
        sorting,
        rowSelection,
        globalFilter,
        columnFilters
    },
    onSortingChange: setSorting,
    onRowSelectionChange: setRowSelection,
    onColumnFiltersChange: setColumnFilters,
    onGlobalFilterChange: setGlobalFilter,
    enableRowSelection: true,
    getCoreRowModel: getCoreRowModel(),
    getSortedRowModel: getSortedRowModel(),
    getFilteredRowModel: getFilteredRowModel()
    // debugTable: true
});

有人知道我如何正确地实现这一目标吗?

基本上,我只想传递一个信号/触发器,以从表本身上方的组件中取消选择表中的所有行。

reactjs 反应表 react-table-v8

评论

0赞 Martial Anouman 10/5/2023
只是为了确保了解您的需求,您想在处理后清除选定的行吗?
0赞 rachitiitr 10/7/2023
你能分享一个代码沙盒链接来复制这个问题吗?

答:

0赞 quentinkrammer 10/5/2023 #1

仅从这段代码中,我无法判断为什么您有一个渲染循环。

但似乎您有 2 个组件,它们都跟踪 RowSelectionState:

  • 较高的组件跟踪“selectedRows”
  • 下部组件跟踪“rowSelection”

这似乎有问题。一个国家应该有一个单一的事实来源。

  • 也许您可以删除“selectedRows”并传递“rowSelection”和“setRowSelection”
  • 使用上下文使 “rowSelection” 和 “setRowSelection” 可用于 react table 组件
  • 使用类似“Jotai”的东西将 rowSelection 状态存储在 react 之外

如果在关闭“严格模式”时渲染循环消失,则 useEffect 导致了问题。 否则,我会怀疑您设置“selectedRows”和“rowSelection”的方式是错误的

2赞 Alaa M 10/7/2023 #2

我已经实现了一个 react-table (v8),带有一个按钮来取消选择所有行。
我在父组件中使用了 ref:

const tableRef = React.useRef(null);

之后,我使用 forwardRef 将该 ref 转发到子组件。

 //Define the methods required for the parent component to interact with the child component
 useImperativeHandle(ref, () => ({
    resetSelectedRows: () => toggleAllRowsSelected(false)
  }));

...

//In the parent component, we can deselect all rows by applying the following
tableRef.current?.resetSelectedRows();

您可以在以下 CodeSandbox 中查看完整功能
编辑 goofy-cherry-vwjm3c

因此,使用这种方法,您可以解决您提出的问题。

评论

0赞 dmikester1 10/9/2023
这对我来说效果很好。谢谢。
2赞 terahertz 10/8/2023 #3

React Tables 通过使用钩子来工作。useReactTable

 const [rowSelection, setRowSelection] = React.useState({});

 const table = useReactTable({
    state: {
      rowSelection, // the state holding which rows are selected
    },
    enableRowSelection: true, //enable row selection for all rows
    onRowSelectionChange: setRowSelection, // handles row selection change
    // other properties
  });

如果选择了第 1 行,则调用该行,并将状态更新为 。setRowSelection{ 1: true }

有几种方法可以解决您的问题。

方法 1 - 将状态向上移动到父组件

您可以通过将状态提升到父组件来提升到父组件。rowSelection

即将以下代码转移到父组件const [rowSelection, setRowSelection] = React.useState({});

然后像这样将其传递给您的子组件:

<Table rowSelection={rowSelection} setRowSelection={setRowSelection} />

在父组件中,您可以使用将所选行状态重置为空。setRowSelection({})

下面是 CodeSandBox 中的一个示例,演示了上述内容。我的示例由一个包含组件的父组件组成,您可以在父组件中重置 React 表。<App><Table>

方法 2 - 使用上下文或状态管理库

为了简单起见,我将使用 React Context。如果表和父组件之间有许多中间组件将重置状态,则需要使用它。您还可以使用其他状态管理库,例如 ZustandReact Redux 而不是 Context。

这个想法很简单。由于您已经知道提供了一个函数,它将重置所有选定的行。然后,我们需要做的就是将对象“向上”传递(到父组件)以使用它。tabletoggleAllRowsSelected()table

要使用 React Context 做到这一点,我们首先创建一个 has 作为状态。TableContextsetTable

import { createContext } from 'react';

export const TableContext = createContext({ setTable: null });

在父组件中,我们创建一个状态,并用 包装子组件。我们还提供状态作为默认值。table<Table>TableContext.Provider

function App() {
  const [table, setTable] = useState();
  
  // other code omitted for brevity
  
  return (
    <TableContext.Provider value={{ setTable }}>
      <Table />
    </TableContext.Provider>
  )

在子组件中,我们使用 hook 来读取和获取函数。我们创建 React 表。创建成功后,我们使用 .父组件现在可以访问该对象。useContextTableContextsetTabletablesetTabletable

function myTable() {
  const { setTable } = useContext(TableContext);

  const reactTable = useReactTable({
    // omitted for brevity
  });

  useEffect(() => {
    if (reactTable) {
      setTable(reactTable); // parent component can now access reactTable
    }
  }, [reactTable, setTable]);
  
  // other code omitted for brevity
}

下面是 Codesandbox 演示 React Context 的示例。

0赞 Afzal K. 10/8/2023 #4

解决此问题的一种方法是在组件中定义一个新函数,该函数负责取消选择所有行。必要时,可以从父组件调用此函数以清除所选行。例如:

const deselectAllRows = () => {
    table.toggleAllRowsSelected(false);
}

然后,在父组件中,您可以利用该函数删除所有选定的行:deselectAllRows()

const clearSelectedRows = () => {
    // perform some action with the selected rows
    // then call the deselectAllRows function
    deselectAllRows();
}

<TableComponent rows={rows} clearSelectedRows={clearSelectedRows} />

toggleAllRowsSelected()函数仅在必要时触发,而不是重复引起循环。