I am making the interactive table using react-table
on my application.
My goal is to make a table that can be editable per row when clicking on a button in a table cell.
I designed an EditableCell
like the following.
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,
};
And my table's definition is: (I used my EditableCell component)
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>
);
};
In setRowEditing
function, I am going to change the state of the current row or its cells so that cells in the row are rendered as the input field or whatever.
But I don't know how to change the state properly.
Could you advise on this?