3

我正在尝试使用反应挂钩编辑/删除材料表中的一行。虽然我可以看到状态正在被修改,但它并没有重新渲染材质表。在 setdata 之后,useeffect 不会触发。

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;

上面的代码最初渲染得很好。但是,当我尝试删除该行时,数据已删除了一行,但 useEffect 不会触发,并且 MaterialTable 组件不会使用新数据呈现。但是,如果我使用注释掉的代码,则 useEffect 会在删除后正常触发。我错过了什么?

4

1 回答 1

5

你不应该改变你的数据来触发 useEffect 钩子或使用 props 和 state 进行反应。问题是,您将相同的对象设置为您的状态挂钩,只是发生了变异。对象引用是相同的,并且 useEffect 将假定没有任何变化。像这样写:

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

过滤器将返回一个新数组,但所选项目将被删除。现在数据是一个新数组,这将触发 useEffect 钩子,因为新旧对象的引用不同。

_.remove(data, row => row._id !== 3)) 还返回一个新数组,如过滤器,它更新挂钩不可变。这将触发 useEffect 钩子并导致重新渲染。希望这可以帮助。快乐编码。

于 2019-08-05T09:43:15.840 回答