Reputation: 109
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)
})
}}
/>
);
}
Upvotes: 0
Views: 4760
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
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
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
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