Amey Karekar
Amey Karekar

Reputation: 53

React Material table editing using hooks

I am trying to edit/delete a row in material table using react hooks. although I can see that the state is being modified, it does not re-render the material table. the useeffect is not firing after the setdata.

import React, { useState, useEffect } from "react";
import faker from "faker";
import MaterialTable from "material-table";
import * as _ from "lodash";

let testData = [];

for (var i = 0; i < 100; i++) {
    testData.push({
        _id: i,
        fullName: faker.name.findName(),
        "email.address": faker.internet.email(),
        phone_number: faker.phone.phoneNumber(),
        address: {
            city: faker.address.city(),
            state: faker.address.state(),
            country: faker.address.country()
        }
    });
}

let columndata = [
    { title: "Id", field: "_id" },
    { title: "Name", field: "fullName" },
    { title: "Email", field: "email.address" },
    { title: "Phone", field: "phone_number" },
    { title: "City", field: "address.city" },
    { title: "State", field: "address.state" },
    { title: "Country", field: "address.country" }
];

const MyDataGrid = () => {
    let [data, setData] = useState(testData);

    useEffect(() => {
        debugger;
        if (data.length < 100) {
            console.log(data.length);
        }
    }, [data]);

    return (
        <MaterialTable
            columns={columndata}
            data={data}
            title="test-table"
            options={{
                filtering: true,
                sorting: true,
                exportButton: true,
                grouping: true
            }}
            editable={{
                onRowDelete: oldData =>
                    new Promise((resolve, reject) => {
                        setTimeout(() => {
                            let newData = data;
                            _.remove(newData, { _id: oldData._id });
                            debugger;
                            setData(newData);
                            resolve();
                        }, 1000);
                    })
            }}
        />
        // <button onClick={() => setData(_.remove(data, row => row._id !== 3))}>
        //     Click me
        // </button>
    );
};

export default MyDataGrid;

The above code renders fine initially. However when I try to delete the row, the data has removed one row, but the useEffect does not fire and the MaterialTable component is not rendered with the new data. If I use the commented out code, though, the useEffect fires fine after the delete. What am I missing?

Upvotes: 3

Views: 5448

Answers (1)

Domino987
Domino987

Reputation: 8774

You should not mutate your data to trigger the useEffect hooks or working with props and state in react in general. The problem is, that you set the same object to your state hook, just mutated. The object reference is the same and useEffect will assume that nothing changed. Write it like this:

new Promise((resolve, reject) => {
                    setTimeout(() => {
                        setData(data.filter(row => row._id !== oldData ._id);
                        resolve();
                    }, 1000);
                })

The filter will return a new array, but the selected item will be removed. Now the data is a new array and this will trigger the useEffect hook, because the refernce of the old and new object differ.

_.remove(data, row => row._id !== 3)) also returns a new array like filter which updates the hook immutable. That will trigger the useEffect hook and cause a rerender. Hope this helps. Happy coding.

Upvotes: 5

Related Questions