Table should rerender and set it's "data" prop to its component state after rerendering component.
i have mui datatable component which renders a table with data from remote api. First component fetches data from api in componentDidMount lifecycle method and then set's that data to components state and renders table with all the columns and data which it get from the component state, but problem occurs when you leave that component and get back to it(or in other words when you rerender component), then display message saying : "Sorry, no matching records found" appears. My first thought was component didn't rerender correctly and table "data" props wasn't updated, but the problem is that component rerenders , component fetches the data from api sets it in component state successfully like before but this time internal table state is not updated, its empty even though component rerendered, i tried rerendering component with different methods using forceUpdate and other methods all the time component is rerendered succesffully but table did not, only refreshing the web page initialize table to render, in fact i have more than 10 components with different data which it successfully fetched from api and set in state, but after leaving and returning to same component in UI table "data" prop didn't update
import React from 'react';
import { withRouter } from 'react-router-dom';
import MUIDataTable from "mui-datatables";
import CustomToolbar from './CustomToolbar';
import axios from 'axios';
import { CircularProgress, Typography } from '@material-ui/core';
class example extends React.Component {
state = {
isLoading: false,
columns: [],
data: []
}
componentDidMount() {
this.getData();
}
componentDidUpdate = (prevProps, prevState) => {
if(prevProps.modelsLoaded !== this.props.modelsLoaded ){
this.setState({columns: this.makeColumns()})
}
}
getData = () => {
this.setState({isLoading: true});
axios.get(`API`).then(res => this.setState({data: res.data, isLoading: false}))
}
makeColumns = () => {
return Object.keys(someProps).map(data=> (
{
name: data,
label: data,
options: {
customFilterListRender: v => `${data}: ${v}`,
filter: true,
sort: true
}
}
))
}
render() {
const { isLoading } = this.state;
let options = {
print: false,
download: false,
serverSide: true,
viewColumns: true,
customToolbar : () => {
return (
<CustomToolbar/>
)
},
selectableRows: 'single'
}
return (
<div>
<MUIDataTable
title={
<Typography variant="h6">
EXAMPLE
{isLoading && <CircularProgress size={24} style={{marginLeft: 15, position: 'relative', top: 4}} />}
</Typography>
}
data={this.state.data}
columns={this.state.columns}
options={options}
/>
</div>
)
}
}
export default withRouter(Example);
| Tech | Version |
|--------------|---------|
| Material-UI | "3.9.2" |
| MUI-datatables | "2.6.4" |
| React | "16.8.2" |
| browser | chrome |
| etc | |
There are some known issues with handling all your column data in state. What I would do is try instead to have a column object in your render function, and only update via state the parts of the column object that need to be updated/changed. Give that a try and see if it works for you.
@gabrielliwerant thank you so much it works perfectly now :), but is there any other solution? because i made my own functionality which requires cellClicking and updating column state on click..
Not at the moment. You should still be able to add a cell click function which changes column state, as long as it's managed separately and bound to the column.
seems that i can't reach column.options.filterList property in that way :/
Sure you can. There's nothing preventing you from doing so in the library that I can see. I recently built this out myself to experiment with something. In pseudocode:
this.state = {
nameFilterList: ['Bob']
};
render() {
const columns: [
{
name: 'Name',
options: { filterList: this.state.nameFilterList }
}
];
options: {
onCellClick: () => this.setState({ nameFilterList: ['Alice'] })
};
return (
<MUIDataTable data={data} columns={columns} options={options} />
);
}
If that doesn't work, feel free to load up a minimal example in codesandbox, and I'll take a look.
@gabrielliwerant thank you for you help :), i made it working just like how i needed although i feel my code is a little bit a mess because of looping through data and columns approach, and i think it would be much easier if onCellClick could return column name but other than that is fine. I will attach example of my code and i hope i can get feedback on that.
url:
https://codesandbox.io/s/blue-shape-364vs
The issue with returning specific column data is that it would then need to include all column data, as you may be looking for name, but someone else might want label, etc. And then it would have to remain up to date whenever new options are added and that all the relevant data can be accessed by the internal table state, which is not a given, and is a source of bugs.
Given all of that, my strong preference is to provide an index, with which developers can grab whatever they want. :)
I get your point, but hey thank you again for helping me out, problem was solved so there is no reason to keep this topic open. :)
There are some known issues with handling all your column data in state. What I would do is try instead to have a column object in your render function, and only update via state the parts of the column object that need to be updated/changed. Give that a try and see if it works for you.
This did the trick for me. Thanks for the suggestion!