Material-table: Functional Components (Hooks) - Editable options

Created on 12 Nov 2019  路  9Comments  路  Source: mbrn/material-table

I'm checking the Editable option, but only has documentation related of React Components (Classes).
I need help to know how to apply the same feature with a Functional Component (Using Hooks)...

https://material-table.com/#/docs/features/editable

onRowUpdate: (newData, oldData) =>
    new Promise((resolve, reject) => {
      setTimeout(() => {
        {
          const data = this.state.data;
          const index = data.indexOf(oldData);
          data[index] = newData;
          this.setState({ data }, () => resolve());
        }
        resolve()
      }, 1000)
    }),

I cannot figure out how to update a state and execute the function resolve().
Does somebody have the same problem?

Find the code right here
https://codesandbox.io/s/materialtableui-b35v3

wontfix

Most helpful comment

I resolved the scenario with a some adjustments to my first code... but I still required your POV to know if this solution is the best approach:

https://codesandbox.io/s/materialtableui-cpxz6

...seems it's working now, basically, I created a state that has the data array, the resolve function of the promise, and a date (Just used as log):

const [gridData, setGridData] = useState({
  data: [
    { name: "Mehmet", surname: "Baran", birthYear: 1987, birthCity: 63 },
    { name: "Zerya Bet眉l", surname: "Baran", birthYear: 2017, birthCity: 34 }
  ],
  resolve: () => {},
  updatedAt: new Date()
});

And to update and resolve the promise I use an effect:

useEffect(() => {
  gridData.resolve();
  console.log("RESOLVE AT:", gridData.updatedAt);
}, [gridData]);

The editable functions:

const onRowAdd = newData =>
  new Promise((resolve, reject) => {
    const { data } = gridData;
    const updatedAt = new Date();
    data.push(newData);
    setGridData({ ...gridData, data, resolve, updatedAt });
  });

const onRowDelete = oldData =>
  new Promise((resolve, reject) => {
    const { data } = gridData;
    const updatedAt = new Date();
    const index = data.indexOf(oldData);
    data.splice(index, 1);
    setGridData({ ...gridData, data, resolve, updatedAt });
  });

const onRowUpdate = (newData, oldData) =>
  new Promise((resolve, reject) => {
    const { data } = gridData;
    const updatedAt = new Date();
    const index = data.indexOf(oldData);
    data[index] = newData;
    setGridData({ ...gridData, data, resolve, updatedAt });
  });

I used a destruct to use the data array of the state into the Material Table:

const { data } = gridData;

return (
  <div className="App">
    <MaterialTable
      ...
      data={data}
      editable={{
        isEditable: rowData => true,
        isDeletable: rowData => true,
        onRowAdd: onRowAdd,
        onRowUpdate: onRowUpdate,
        onRowDelete: onRowDelete
      }}
    />
  </div>
);

...this approach is the best? Or have some flaws that I not see...

Thanks!

All 9 comments

I resolved the scenario with a some adjustments to my first code... but I still required your POV to know if this solution is the best approach:

https://codesandbox.io/s/materialtableui-cpxz6

...seems it's working now, basically, I created a state that has the data array, the resolve function of the promise, and a date (Just used as log):

const [gridData, setGridData] = useState({
  data: [
    { name: "Mehmet", surname: "Baran", birthYear: 1987, birthCity: 63 },
    { name: "Zerya Bet眉l", surname: "Baran", birthYear: 2017, birthCity: 34 }
  ],
  resolve: () => {},
  updatedAt: new Date()
});

And to update and resolve the promise I use an effect:

useEffect(() => {
  gridData.resolve();
  console.log("RESOLVE AT:", gridData.updatedAt);
}, [gridData]);

The editable functions:

const onRowAdd = newData =>
  new Promise((resolve, reject) => {
    const { data } = gridData;
    const updatedAt = new Date();
    data.push(newData);
    setGridData({ ...gridData, data, resolve, updatedAt });
  });

const onRowDelete = oldData =>
  new Promise((resolve, reject) => {
    const { data } = gridData;
    const updatedAt = new Date();
    const index = data.indexOf(oldData);
    data.splice(index, 1);
    setGridData({ ...gridData, data, resolve, updatedAt });
  });

const onRowUpdate = (newData, oldData) =>
  new Promise((resolve, reject) => {
    const { data } = gridData;
    const updatedAt = new Date();
    const index = data.indexOf(oldData);
    data[index] = newData;
    setGridData({ ...gridData, data, resolve, updatedAt });
  });

I used a destruct to use the data array of the state into the Material Table:

const { data } = gridData;

return (
  <div className="App">
    <MaterialTable
      ...
      data={data}
      editable={{
        isEditable: rowData => true,
        isDeletable: rowData => true,
        onRowAdd: onRowAdd,
        onRowUpdate: onRowUpdate,
        onRowDelete: onRowDelete
      }}
    />
  </div>
);

...this approach is the best? Or have some flaws that I not see...

Thanks!

i used the code above that @mbv401920150 provided as an example to solve my onRowUpdate issue. Thank you so much.

Hi, I used the code you provided @mbv401920150 and it worked fine, but when I changed ir to receive data from props it stoped updating.
I edit a field, and data changes in the state and variables, but the table renders the old data.
I only changed this:

const [gridData, setGridData] = useState({
    data: props.data,
    resolve: () => {},
    updatedAt: new Date()
  });

Originally I had a callback to a parent component that handles the data request and logic. That callback changed the state in the parent, that was then passed as props to the table. But I removed all of that, trying simply to take data from props, and then updating the state within the table component.

I print the data variable to the console before rendering, and it contains the new values, except for a tableData element.

const { data } = gridData;
  console.log("State", data)
  return (
    <div>
    ...

console output:

(3) [{鈥, {鈥, {鈥]
0: {param: "Admin", val: "0"}
1: {param: "Margin", val: "0.4", tableData: {鈥}
2: {param: "Price", val: "5080", tableData: {鈥}
length: 3
__proto__: Array(0)

initial data printed to console:

(3) [{鈥, {鈥, {鈥]
0: {param: "Admin", val: "0.03", tableData: {鈥}
1: {param: "Margin", val: "0.4", tableData: {鈥}
2: {param: "Price", val: "5080", tableData: {鈥}
length: 3
__proto__: Array(0)

Any Ideas?

@DanielFerszt - add a key to the table that is randomly set to force the refresh:

const [refreshKey, setRefreshKey] = useState(Math.random())

useEffect(() => {
  gridData.resolve();
  setRefreshKey(Math.random())
  console.log("RESOLVE AT:", gridData.updatedAt);
}, [gridData]);

<MaterialTable key={refreshKey}

Thanks, I'll try that. I solved the issue by adding a second state for the columns and refreshing that with every edit too... That forced the table to refresh.

I have also set the tableRef and called onQueryChange to force a refresh as well on row edits.

Hey,

Can you please guys @TroySchmidt or @DanielFerszt provide a working exemple of your guys solution. I'm trying to move my project to react hooks and I'm not able to have my props containing the data of my table, passed down to that material-table.

I tried the refreshed keys already trick, but didn't make any difference.

    const [refreshKey, setRefreshKey] = useState(Math.random())
    const [gridData, setGridData] = useState({
  data: props.ingredients
  resolve: () => {}});

useEffect(() => {
  gridData.resolve();
  setRefreshKey(Math.random())

}, [gridData]);

Sure, here is a link to my question in stackOverflow where someone answered very well. He even explains a little more in the comments at my request.

https://stackoverflow.com/questions/60935643/react-material-table-editing-from-props-using-hooks/60957646?noredirect=1#comment107850018_60957646

Let me know it you need more help!

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. You can reopen it if it required.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

behrouz-s picture behrouz-s  路  3Comments

VipinJoshi picture VipinJoshi  路  3Comments

jlgreene2 picture jlgreene2  路  3Comments

diegosps picture diegosps  路  3Comments

ModPhoenix picture ModPhoenix  路  3Comments