单击具有反应的单元格上的 "Edit" 按钮时如何使行 editable-table

How to make the row editable when clicking on an "Edit" button on a cell with react-table

我正在我的应用程序上使用 react-table 制作交互式 table。

我的目标是制作一个 table,当单击 table 单元格中的按钮时,每行可以编辑 table。

我设计了一个 EditableCell 如下所示。

import React, {useState} from "react";

export const EditableCell = ({
                                 value: initialValue,
                                 row: Row,
                                 column: {id, editable, state},
                                 isEditing,
                                 updateItem, // This is a custom function that we supplied to our table instance
                             }) => {
    // We need to keep and update the state of the cell normally
    const [value, setValue] = React.useState(initialValue);
    const {index} = Row;

    const onChange = e => {
        setValue(e.target.value);
    };

    // We'll only update the external data when the input is blurred
    const onBlur = () => {
        updateItem(index, id, value);
    }

    // If the initialValue is changed external, sync it up with our state
    React.useEffect(() => {
        setValue(initialValue)
    }, [initialValue]);

    /**
     * Event handler to make a row editable.
     * @param e
     */
    const setRowEditing = (e) => {
        // TODO
    };

    let retObj = null;
    if (isEditing && editable) {
        switch (id) {
            default:
                retObj = <input className="input-edit w-100" value={value} onChange={onChange} onBlur={onBlur}/>;
                break;
        }
    } else {
        switch (id) {
            case 'action_btn':
                retObj = <>
                    <button className="btn btn-sm btn-info btn-sm-td" onClick={setRowEditing}>{ isEditing? "Save" : "Edit"}</button>
                </>;
                break;
            default:
                retObj = <div>{value}</div>;
                break;
        }
    }
    return retObj;
}

export const defaultColumn = {
    Cell: EditableCell,
};

而我的 table 的定义是:(我使用了我的 EditableCell 组件)

export default function Table({ columns, data, updateItem }) {

    // Use the useTable Hook to send the columns and data to build the table
    const {
        getTableProps, // table props from react-table
        getTableBodyProps, // table body props from react-table
        headerGroups, // headerGroups, if your table has groupings
        rows, // rows for the table based on the data passed
        prepareRow // Prepare the row (this function needs to be called for each row before getting the row props)
    } = useTable({
        columns,
        data,
        defaultColumn,
        updateItem,
    }, useBlockLayout, useRowState);

    /*
      Render the UI for your table
      - react-table doesn't have UI, it's headless. We just need to put the react-table props from the Hooks, and it will do its magic automatically
    */
    return (
        <table className="data-table" {...getTableProps()}>
            <thead>
            {headerGroups.map(headerGroup => (
                <tr {...headerGroup.getHeaderGroupProps()}>
                    {headerGroup.headers.map(column => (
                        <th {...column.getHeaderProps()}>{column.render("Header")}</th>
                    ))}
                </tr>
            ))}
            </thead>
            <tbody {...getTableBodyProps()}>
            {rows.map((row, i) => {
                prepareRow(row);
                return (
                    <tr {...row.getRowProps()}>
                        {row.cells.map(cell => {
                            return <td {...cell.getCellProps()}>{cell.render("Cell")}</td>;
                        })}
                    </tr>
                );
            })}
            </tbody>
        </table>
    );
};

setRowEditing 函数中,我将更改当前行或其单元格的状态,以便该行中的单元格呈现为输入字段或其他内容。

但是我不知道如何正确地改变状态。

你能就此提出建议吗?

在您传递给 React 的列数组中 table 您需要创建一个按钮,该按钮的 onClick 函数需要一个回调来编辑您的数据以添加一个 isEditing: true 因此您将处理从 table 外部将行转换为编辑模式。 editable 单元格中不需要 setRowEditing

函数设置 table 数据 'isEditing' 属性

const handleClickEditRow = (rowIndex) => {
    setTableData(prev => prev.map((r, index) => ({...r, isEditing: rowIndex === index})))
}

在您的专栏中

{
    accessor: '[editButton]',
    Cell: (cellObj) => <button onClick={() => handleClickEditRow(cellObj.row.index)}>Edit</button>
}

我试图通过执行以下步骤实现此 feature/functionality:

// leverage useState react hook.     
const [editableRowIndex, setEditableRowIndex] = React.useState(null);

状态变量的初始值为空 - 因此所有行都不会打开进行编辑。

将状态变量和方法传递给 useTable() 根挂钩。 自定义插件挂钩和其他 variables/methods 维护组件状态从 table 实例返回。这些您以后可以从任何地方检索。

您可以根据状态变量渲染 Editable 单元格组件和自定义插件挂钩(在本例中为编辑挂钩)。

const {
    // all your hooks...
  } = useTable(
    {
      columns,
      data,
      // all your other hooks...
      updateMyData,
      **// pass state variables so that we can access them in edit hook later
      editableRowIndex, // index of the single row we want to edit 
      setEditableRowIndex // setState hook for toggling edit on/off switch**
    },
    // other hooks... 
    (hooks) => {
      hooks.allColumns.push((columns) => [
        // other hooks such as selection hook
        ...columns,
        // edit hook
        {
          accessor: "edit",
          id: "edit",
          Header: "edit",
          Cell: **({ row, setEditableRowIndex, editableRowIndex })** => (
            <button
              className="action-button"
              onClick={() => {
                **const currentIndex = row.index;
                if (editableRowIndex !== currentIndex) {
                  // row requested for edit access
                  setEditableRowIndex(currentIndex);
                } else {
                  // request for saving the updated row
                  setEditableRowIndex(null); // keep the row closed for edit after we finish updating it
                  const updatedRow = row.values;
                  console.log("updated row values:");
                  console.log(updatedRow);
                  // call your updateRow API
                }**
              }}
            >
              *{/* single action button supporting 2 modes */}*
              **{editableRowIndex !== row.index ? "Edit" : "Save"}**
            </button>
          )
        }
      ]);
    }
  );

示例可在以下 link 中找到:

代码沙箱link: https://codesandbox.io/s/github/smmziaul/only-one-row-editable

github 回购 link: https://github.com/smmziaul/only-one-row-editable