【问题标题】:React Material-Table editing from props using hooks使用钩子从道具中反应材料表编辑
【发布时间】:2020-07-11 02:56:27
【问题描述】:

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

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

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>
    );
}

【问题讨论】:

  • 如果问题出在props.cols,你应该告诉我们你是如何传递这个属性的。
  • 是的,对不起。我将代码添加到问题中。
  • 我正在测试你的代码,它对我有用吗?我将数据和列添加为props,并添加了缺少的onRowUpdate, onRowDelete,它似乎工作正常。这是codesandbox
  • 谢谢@awran5。我测试了沙箱代码,如果您按下编辑按钮,然后更改一个值并接受,该字段将恢复为原始值。但是,如果您声明 const comoscol = [...] 并使用它而不是道具,它将正常工作。我不明白为什么
  • @Danf 是的,我明白了问题所在。请在下面查看我的答案。

标签: reactjs material-table


【解决方案1】:

我不太确定导致此问题的原因,但当列数据作为 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 也是如此

【讨论】:

  • 谢谢!两种方法都有效。我和第二个一起去。但是,我之前确实尝试过,但没有成功……唯一的区别是这一行:let data = [...gridData.data];,在我的代码中是const { data } = gridData;。有什么区别?如果不是太多要求!
  • 当然,不客气。 let data = [...gridData.data]es6 的方法,通过将 gridData.data 解构为数组 [...] 并将值分配给 data,将 gridData.data 复制到一个新数组中,但 { data } = gridData 只是解构(取出) data 来自gridData.data
猜你喜欢
  • 2019-12-12
  • 1970-01-01
  • 2022-06-30
  • 2019-08-21
  • 1970-01-01
  • 2021-01-09
  • 1970-01-01
  • 1970-01-01
  • 2020-11-22
相关资源
最近更新 更多