React TanStack

使用React TanStack添加和删除表格的行

使用React TanStack实现有多行选择的表格的添加和删除行功能的指南。

2024年2月15日
React-Add-Remove-Table-Rows
分享

上一部分中,我们详细介绍了创建具有动态列模式的可编辑 React 表格的方法。我们还利用 TanStack Table 来简化这个过程。

在本文,我们将继续在之前所做的基础上进行构建,并给具有多行选择的表格增加删除和添加行的功能。

下面展示了我们希望在本教程结束时表格的外观和行为:

tanstack2-1

添加表格行

要启用添加表格行,我们必须添加“添加行”按钮,然后创建逻辑以将空行插入数据数组。

让我们首先添加在主表组件中插入行的逻辑。与之前的方法一样,我们将在useReactTableHook中的meta对象中添加。这样,我们就可以通过主table对象在任何地方访问它:

const table = useReactTable({
    data,
    columns,
    getCoreRowModel: getCoreRowModel(),
    meta: {
      editedRows,
      setEditedRows,
      revertData: (...) => {
        ...
      },
      updateData: (...) => {
        ...
      },
      addRow: () => {
        const newRow: Student = {
          studentId: Math.floor(Math.random() * 10000),
          name: "",
          dateOfBirth: "",
          major: "",
        };
        const setFunc = (old: Student[]) => [...old, newRow];
        setData(setFunc);
        setOriginalData(setFunc);
      },
    },
  });

请注意,我们还更新了originalData数组,因为我们需要使它们保持同步,以实现第一部分中讨论的取消/保存行功能。

现在,我们可以创建一个带有按钮和事件处理程序的页脚单元组件来使用该addRow函数。

export const FooterCell = ({ table }) => {
  const meta = table.options.meta
  return (
    <div className="footer-buttons">
      <button className="add-button" onClick={meta?.addRow}>
        Add New +
      </button>
    </div>
  )
}

最后,我们需要将FooterCell组件显示在表格上的某个位置以供用户使用。有多种选择,但将其添加到页脚的主表可能是一个好地方,因为它会看起来更加集成。

import { FooterCell } from '../Table/FooterCell';

export const Table = () => {
  const [data, setData] = useState(() => [...defaultData]);
  const [originalData, setOriginalData] = useState(() => [...defaultData]);
  const [editedRows, setEditedRows] = useState({});

  const table = useReactTable({
    data,
    columns,
    getCoreRowModel: getCoreRowModel(),
    meta: {
      editedRows,
      setEditedRows,
      revertData: (...) => {
        ...
      },
      updateData: (...) => {
        ...
      },
      addRow: () => {
        const newRow: Student = {
          studentId: Math.floor(Math.random() * 10000),
          name: "",
          dateOfBirth: "",
          major: "",
        };
        const setFunc = (old: Student[]) => [...old, newRow];
        setData(setFunc);
        setOriginalData(setFunc);
      },
    },
  });

  return (
    <article className="table-container">
      <table>
        <thead>
          ...
        </thead>
        <tbody>
          ...
        </tbody>
        <tfoot>
          <tr>
            <th colSpan={table.getCenterLeafColumns().length} align="right">
              <FooterCell table={table} />
            </th>
          </tr>
        </tfoot>
      </table>
    </article>
  );
};

下面是上面代码的一个实时示例,带有如下按钮样式:

tanstack2-2
table .footer-buttons button {
  border: none;
  background-color: transparent;
}

table .add-button {
  color: #4bbd7f;
}

删除表格行

删除表格行将遵循与上一节相同的方法。让我们首先添加removeRow函数,这是一种简单的单行过滤方法,用于从数据和原始数据数组中删除行。

const table = useReactTable({
    data,
    columns,
    getCoreRowModel: getCoreRowModel(),
    meta: {
      editedRows,
      setEditedRows,
      revertData: (...) => {
        ...
      },
      updateData: (...) => {
        ...
      },
      addRow: () => {
        ...
      },
      removeRow: (rowIndex: number) => {
        const setFilterFunc = (old: Student[]) =>
          old.filter((_row: Student, index: number) => index !== rowIndex);
        setData(setFilterFunc);
        setOriginalData(setFilterFunc);
      },
    },
  });

对于“删除”按钮,不需要创建新组件,因为它将位于EditCell组件中“编辑”按钮旁边。

现在,我们可以在EditCell组件中添加一个removeRow函数,并在“删除”按钮的onClick事件上调用它。

export const EditCell = ({ row, table }) => {
  const meta = table.options.meta;

  const setEditedRows = (...) => {
   ...
  };

  const removeRow = () => {
    meta?.removeRow(row.index);
  };

  return (
    <div className="edit-cell-container">
      {meta?.editedRows[row.id] ? (
        <div className="edit-cell-action">
          <button onClick={setEditedRows} name="cancel">
            ⚊
          </button>{" "}
          <button onClick={setEditedRows} name="done">
            ✔
          </button>
        </div>
      ) : (
        <div className="edit-cell-action">
          <button onClick={setEditedRows} name="edit">
            ✐
          </button>
          <button onClick={removeRow} name="remove">
            X
          </button>
        </div>
      )}
    </div>
  );
};

请注意,为了更清晰起见,我们将“取消”图标更改为减号 (⚊),将“删除”图标更改为叉号 (X)。

下面是上面代码的现场演示,其中包含一些按钮样式和对齐方式:

tanstack2-3
table .edit-cell-action button[name="edit"] {
  color: #ffb918;
}

table .edit-cell-action button[name="cancel"] {
  color: #7b7b7b;
}

table .edit-cell-action button[name="done"] {
  color: #4bbd7f;
}

table .edit-cell-action button[name="remove"] {
  color: red;
  background-color: rgb(230, 208, 208);
}

table .edit-cell-action {
  display: flex;
  gap: 5px;
}

删除表格的多行

一次选择和删除多行总是很有帮助的。幸运的是,TanStack Table 提供开箱即用的行选择功能。我们需要做的就是启用该功能并传入正确的方法;它将为我们管理剩下的事情。

首先,我们将在useReactTable中添加enableRowSelection并创建一个新的removeSelectedRows函数。该函数将接收选定行 ID 的数组,并将其从data数组中过滤掉。

const table = useReactTable({
  data,
  columns,
  getCoreRowModel: getCoreRowModel(),
  enableRowSelection: true,
  meta: {
    editedRows,
    setEditedRows,
    revertData: (...) => {
      ...
    },
    updateData: (...) => {
      ...
    },
    addRow: () => {
      ...
    },
    removeRow: (...) => {
      ...
    },
    removeSelectedRows: (selectedRows: number[]) => {
      const setFilterFunc = (old: Student[]) =>
        old.filter((_row, index) => !selectedRows.includes(index));
      setData(setFilterFunc);
      setOriginalData(setFilterFunc);
    },
  },
});

然后,在EditCell组件中,我们将添加一个带有适当属性的复选框,以捕获和更新所选行。事件处理程序来自useReactTable钩子中可供我们使用的row对象。

export const EditCell = ({ row, table }) => {
  const meta = table.options.meta;

  const setEditedRows = (...) => {
    ...
  };

  const removeRow = () => {
    meta?.removeRow(row.index);
  };

  return (
    <div className="edit-cell-container">
      {meta?.editedRows[row.id] ? (
        <div className="edit-cell-action">
          <button onClick={setEditedRows} name="cancel">
            ⚊
          </button>{" "}
          <button onClick={setEditedRows} name="done">
            ✔
          </button>
        </div>
      ) : (
        <div className="edit-cell-action">
          <button onClick={setEditedRows} name="edit">
            ✐
          </button>
          <button onClick={removeRow} name="remove">
            X
          </button>
        </div>
      )}
      <input
        type="checkbox"
        checked={row.getIsSelected()}
        onChange={row.getToggleSelectedHandler()}
      />
    </div>
  );
};

最后,我们将向FooterCell组件添加一个新Remove Selected按钮并从meta对象传入removeSelectedRows函数。可以从具有rows属性的getSelectedRowModel函数中检索选定的行。

export const FooterCell = ({ table }) => {
  const meta = table.options.meta
  const selectedRows = table.getSelectedRowModel().rows

  const removeRows = () => {
    meta.removeSelectedRows(
      table.getSelectedRowModel().rows.map(row => row.index)
    )
    table.resetRowSelection()
  }

  return (
    <div className="footer-buttons">
      {selectedRows.length > 0 ? (
        <button className="remove-button" onClick={removeRows}>
          Remove Selected x
        </button>
      ) : null}
      <button className="add-button" onClick={meta?.addRow}>
        Add New +
      </button>
    </div>
  )
}

此外,我们添加了一个条件,仅当存在选定行时才显示Remove Selected按钮。

下面是最终的演示,以及Remove Selected按钮和复选框的其余样式:

tanstack2-4
table .edit-cell-container {
  display: flex;
  justify-content: end;
  align-items: center;
  gap: 4px;
}

table input[type="checkbox"] {
  width: 16px;
  height: 16px;
}

table .remove-button {
  color: #e44747;
}

完整代码

完整的代码可以在这个仓库中找到。如果您喜欢本教程,请为仓库加星,并随时提出新功能的需求!

总结

在本教程中,我们学习了如何在 React 表格中添加和删除行。我们还学习了如何添加复选框以通过单击选择和删除多行。

来自:https://muhimasri.com/blogs/add-remove-react-table-rows/

更多文章

使用TanStack的动态列模式创建React可编辑表格单元格和行的综合指南。

2024年2月14日 · React TanStack
refine
用于构建内部工具、管理面板、仪表板和B2B应用程序的React框架,具有无与伦比的灵活性。
2024年2月4日 · React
indexed-pages
48小时内让您的网站在谷歌上建立索引的脚本。
2024年2月2日 · SEO 谷歌
excalidraw
一款开源的手绘风格的虚拟白板,支持协作和端到端加密。
2024年2月1日 · 白板