Zink
Zink

Reputation: 109

Material Table can not update

I am using Material-Table to create a table that loads data from an API that I made. When the page loads, the table properly loads and displays the data. But once I try to edit and update the data, all data gets lost and a message saying no data shows up on the table. What am I doing wrong?

My Code:

import React, { useState, useEffect } from "react";
import "./Complaints.css";
import { API } from "aws-amplify";
import MaterialTable from 'material-table';

export default function Complaints(props) {

    const [complaint, setComplaint] = useState([]);
    const [isLoading, setIsLoading] = useState(true);
    const [isInEditMode, setIsEditMode] = useState(false);
    const [defaultValue, setDefaultValue] = useState("");
    const [state, setState] = useState({
        columns: [
            { title: 'Customer ID', field: 'id', editable: 'never' },
            { title: 'Issue', field: 'complaintName', editable: 'never' },
            { title: 'Description', field: 'complaintDescription', editable: 'never'},
            { title: 'Order ID', field: 'complaintOrderId', editable: 'never'},
            { title: 'Submitted', field: 'createdAt', editable: 'never'},
            { title: 'Updated', field: 'updatedAt', editable: 'date'},
            { title: 'Admin Comment', field: 'adminComment', editable: 'onUpdate'},
        ],
        complaint: []
    });

    var columsArr = [
        { title: 'Customer ID', field: 'id', editable: 'never' },
        { title: 'Issue', field: 'complaintName', editable: 'never' },
        { title: 'Description', field: 'complaintDescription', editable: 'never'},
        { title: 'Order ID', field: 'complaintOrderId', editable: 'never'},
        { title: 'Submitted', field: 'createdAt', editable: 'never'},
        { title: 'Updated', field: 'updatedAt', editable: 'date'},
        { title: 'Admin Comment', field: 'adminComment', editable: 'onUpdate'},
    ];

    useEffect(() => {
        async function onLoad() {
            if (!props.isAuthenticated) {
                return;
            }

            try {
                const complaint = await loadComplaint();
                setComplaint(complaint);
                setState({
                    columns: [state.columns, ...columsArr],
                    complaint: [...state.complaint, ...complaint]
                });
                console.log(complaint)
            } catch (e) {
                alert(e);
            }

            setIsLoading(false);
        }

        onLoad();
    }, [props.isAuthenticated]);

    function loadComplaint() {
        return API.get("kleen", "/Complaint");
    }

    // function edit(adminComment) {
    //     setIsEditMode(true);
    //     setDefaultValue(adminComment);
    //     console.log("value is"+ adminComment);
    // }

    // function updateComplaint() {
    //     return API.put("kleen", `/Complaint/${props.}`);
    // }

    return (
        <MaterialTable style={{
            marginTop: "8rem",
            marginLeft: "auto",
            marginRight: "auto",
            position: "sticky",
        }}
            title="Complaints"
            columns={state.columns}
            data={state.complaint}
            editable={{
                onRowUpdate: (newData, oldData) =>
                    new Promise(resolve => {
                        setTimeout(()=> {
                            {
                                const data = state.complaint;
                                const index = data.indexOf(oldData);
                                data[index] = newData;
                                setState({data}, () => resolve());
                            }
                            resolve()
                        }, 1000)
                        })
            }}
        />
    );
}

Table before the edit: enter image description here

Table after saving an edit: enter image description here

Upvotes: 0

Views: 4760

Answers (4)

Muhammad Awais
Muhammad Awais

Reputation: 1986

In my case, material table wasn't updating itself when data was updated, the reason behind that was I was directly updating react component state variable which we shouldn't do if this is a state variable

const [todos, setTodos] = useState<Todo[]>([]);

then while updating it, first make copy, update copy and then call setFunction like this

let copyArr: Todo[] = JSON.parse(JSON.stringify(todos));
copyArr.push(newTodo)
setTodos(copyArr)

Upvotes: 0

jhonatan_yachi
jhonatan_yachi

Reputation: 361

In your code:

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

At this line "const data = state.complaint;", I think your "data" is a reference of state.complaint, and in some cases I had problems with that "setState({data}, () => resolve())" function, since material can't update.

You can try this:

const data = [...state.complaint];

Upvotes: 0

Michael P
Michael P

Reputation: 41

In case you provide the data to the table from the parent component:

state.data - data array of the table

static getDerivedStateFromProps(props, state) {
    // Any time the current user changes,
    // Reset any parts of state that are tied to that user.
    // In this simple example, that's just the email.
    if (props.data !== state.data) {
        return {
            data: props.data,
        };
    }
    return null;
}

    render() {
    return (
        <MaterialTable
            title={<h1>All the leads</h1>}
            columns={this.state.columns}
            data={this.state.data}..........

Upvotes: 2

Domino987
Domino987

Reputation: 8804

There are quite a few bugs in your code I am afraid.

First, you have duplicated data since you are saving the complaint in its own useState and in the second useState (with columns). Since you never save anything in the complaint useState, you can delete it.

You also create a new column variable on each render but you already have the same object in the useState. After you download the entries, you can access the columns like this which reduces duplication:

setState(prevState => ({
         ...prevState,
          complaint: [...state.complaint, ...complaint]
  }));

You are also using the complaint variable name twice, which should be avoided.

You need to spread your data into an array not an object in the setState like this: setState(prevState => ({...prevState, ...data}), () => resolve()); or else you create an object that looks like this:

{
   data: Your_data_array
}

and set it to the current state. You loose both your columns values and your data values are not accessibly anymore. This object is not readable by material-table, since it expects an array.

Try that and see if it works.

Upvotes: 0

Related Questions