使用钩子从道具编辑React Material Table



我正在构建一个应用程序,该应用程序将从API请求数据,并将其显示在可编辑的表中,用户可以在其中编辑和更新数据库。我正在使用React与材料ui和材料表。

我将在父组件的状态下初始化数据,并将其作为道具传递给呈现表的子组件。出于测试目的,我初始化状态中的数据,以模拟道具的后期实现。该表渲染正确,但在编辑时,值不会更改。

export default function Table(props){
const [gridData, setGridData] = useState({
data: [
{ param: "Admin", val: "0.03" },
{ param: "Margin", val: "0.4" },
{ param: "Price", val: "5080" },
],
resolve: () => {}
});
useEffect(() => {
gridData.resolve();
}, [gridData]);
const onRowUpdate = (newData, oldData) =>
new Promise((resolve, reject) => {
const { data } = gridData;
const index = data.indexOf(oldData);
data[index] = newData;
setGridData({ ...gridData, data, resolve });
});
const { data } = gridData;
return (
<div>
<MaterialTable
columns={props.col}
data={data}
editable={{
isEditable: rowData => true,
isDeletable: rowData => true,
onRowUpdate: onRowUpdate
}}
/>
</div>
);
}

现在,我发现当我用以下内容替换columns={props.col}行时,该表可以正常工作:

columns={[
{ title: 'Parameters', field: 'param', editable: 'never' },
{ title: 'Value', field: 'val', editable: 'onUpdate' }
]}

因此,我的问题似乎是列,而不是数据。

如有任何帮助,我们将不胜感激!

注意:代码基于github的以下响应:https://github.com/mbrn/material-table/issues/1325

编辑:列从父组件传递,如下所示:

const comonscol = [
{ title: 'Parameters', field: 'param', editable: 'never' },
{ title: 'Value', field: 'val', editable: 'onUpdate' }
];
export default function ParamsSection(props) {
...
return (
<div>
...
<Table col={comonscol} data={dummy2} />
... 
</div>
);
}

我不太确定是什么导致了这个问题,但当列数据作为porps传递时,MaterialTable组件似乎不会触发重新渲染

以下是我修复它的方法:

第一种方法:

为列创建一个新的state,并通过useEffect:更新列来触发重新渲染

const [gridData, setGridData] = useState(props.data);
const [columns, setcolumns] = useState(props.col);
useEffect(() => {
gridData.resolve();
// update columns from props
setcolumns(props.col);
}, [gridData, props.col]);
...
const onRowUpdate = (newData, oldData) =>
new Promise((resolve, reject) => {
// Reset the columns will trigger re-render as the state has changed 
// then it will update by useEffect
setcolumns([]);
const { data } = gridData;
const updatedAt = new Date();
const index = data.indexOf(oldData);
data[index] = newData;
setGridData({ ...gridData, data, resolve, updatedAt });
});

codeSandbox示例。


第二种方法:

data, columns合并到对象的状态中,并制作道具数据的副本,然后使用该副本。(为了测试,我更改了一些日期结构(

// Parent
const data = [
{ param: "Admin", val: "0.03" },
{ param: "Margin", val: "0.4" },
{ param: "Price", val: "5080" }
];
const comonscol = [
{ title: "Parameters", field: "param" },
{ title: "Value", field: "val" }
];
... 
<Table col={comonscol} data={data} />

// Table.js
const [gridData, setGridData] = useState({
data: props.data,
columns: props.col,
resolve: () => {},
updatedAt: new Date()
});
const onRowUpdate = (newData, oldData) =>
new Promise((resolve, reject) => {
// Copy current state data to a new array
const data = [...gridData.data];
// Get edited row index
const index = data.indexOf(oldData);
// replace old row
data[index] = newData;
// update state with the new array
const updatedAt = new Date();
setGridData({ ...gridData, data, updatedAt, resolve });
});

codeSandbox示例。


注意:这里以onRowUpdate为例,onRowAdd, onRowDelete也是如此

最新更新