单击带有反应表的单元格上的“编辑”按钮时如何使行可编辑

Lik*_*rus 11 reactjs react-table-v7

我正在我的应用程序中使用交互式表格react-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,
};
Run Code Online (Sandbox Code Playgroud)

我的表格的定义是:(我使用了 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>
    );
};
Run Code Online (Sandbox Code Playgroud)

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

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

你能就此提出建议吗?

小智 6

在传递到反应表的列数组中,您需要创建一个按钮,该按钮的onClick函数接受回调来编辑数据以添加一个按钮isEditing: true,以便您可以从表外部将行转变为编辑模式。不需要setRowEditing在可编辑单元格中。

使用“isEditing”属性设置表数据的函数

const handleClickEditRow = (rowIndex) => {
    setTableData(prev => prev.map((r, index) => ({...r, isEditing: rowIndex === index})))
}
Run Code Online (Sandbox Code Playgroud)

在你的专栏中

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


SOO*_*.M. 4

I tried to achieve this feature/functionality by doing the following steps:

// leverage useState react hook.     
const [editableRowIndex, setEditableRowIndex] = React.useState(null);
Run Code Online (Sandbox Code Playgroud)

Our initial value for the state variable is null - so that all the rows are not open for edit.

Pass the state variable and method to the useTable() root hook. custom plugin hooks and other variables/methods maintaining the component state are returned from the table instance. These you can later retrieve from anywhere you want.

You can render the Editable Cell Component and custom plugin hook (edit hook, in this case) according to the state variables.

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>
          )
        }
      ]);
    }
  );
Run Code Online (Sandbox Code Playgroud)

An example can be found in the following links:

code sandbox link: https://codesandbox.io/s/github/smmziaul/only-one-row-editable

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