I am using material-table (https://material-table.com/#/) which is built with React.
I have data coming in as a prop to material-table like shown in the code below. I usually click a button in the parent component to change the prop in the Performancetbl component. But when i click on the button once, table is not rerendering with new data. When I click on it one more time, it rerenders though. Why is that happening?
I tried to save props into a state variable state in Performancetbl component, but that did not change the behavior at all.
I also tried console.log(props.datas)
to see if correct data is appearing the first time I click on the button. And it is indeed the correct value! Can you guys figure out why this is happening?
function Performancetbl(props) {
const options = {
...
};
console.log(props.datas)
return(
<div style={{ maxWidth: "100%" }}>
<MaterialTable
title="Overall"
data={props.datas}
columns={props.columns}
options={options}
components={props.components}
/>
</div>
);
}
export default Performancetbl;
Thanks!
The reason this is most likely happening to you is because you are rendering the table before data has arrived.
Please see the following demo on how to grab data from an API and pass it via props.
ParentComponent.js
import React, { useState } from "react";
import AppTable from "./AppTable";
export default function ParentComponent() {
const [tableData, setTableData] = useState([]);
const [isLoading, setIsLoading] = useState(false);
const columns = [
{
title: "Id",
field: "id"
},
{
title: "UserId",
field: "userId"
},
{
title: "Title",
field: "title"
},
{
title: "Completed",
field: "completed"
}
];
const tableDiv = {
marginTop: "30px"
};
const shadowStyle = {
boxShadow: "0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19)"
};
const btnStyle = {
height: "40px",
width: "300px",
fontSize: "24px",
cursor: "pointer",
...shadowStyle
};
const headStyle = {
textAlign: "center",
padding: "20px",
backgroundColor: "lightcoral",
...shadowStyle
};
const sleep = time => {
return new Promise(resolve => setTimeout(resolve, time));
};
const fetchData = async () => {
setIsLoading(true);
// Add a timeout to give the appearance of long load times
await sleep(3000);
try {
const resp = await fetch("https://jsonplaceholder.typicode.com/todos");
const json = await resp.json();
setTableData(json);
} catch (err) {
console.trace(err);
alert(err.message + "\r\n\r\nSee console for more info.");
}
setIsLoading(false);
};
return (
<div>
<div style={headStyle}>
<h1>Click button to get data</h1>
<button style={btnStyle} onClick={fetchData}>
Click Me To Get API Data
</button>
</div>
<div style={tableDiv}>
<AppTable data={tableData} columns={columns} isLoading={isLoading} />
</div>
</div>
);
}
AppTable.js (uses material-table
)
import React from "react";
import MaterialTable from "material-table";
import tableIcons from "./TableIcons.js";
export default function AppTable({ data, columns, ...rest }) {
return (
<MaterialTable
{...rest}
icons={tableIcons}
columns={columns}
data={data}
/>
);
}