Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Filters reset / ignored on parent state change #160

Closed
martindeanlund opened this issue Jan 16, 2019 · 13 comments
Closed

Filters reset / ignored on parent state change #160

martindeanlund opened this issue Jan 16, 2019 · 13 comments
Assignees
Labels
bug Something isn't working

Comments

@martindeanlund
Copy link

Whenever the state of a parent is set the table loses its filter controls.

1 - Add a value to a column filter
2 - Trigger setState on the parent component
3 - Observe that the table is no longer filtered (even if the HTML input box has text)

Expected behavior: Filter selections persist in the table state and are applied whenever the table is rendered.

I suspect this has to do with the UNSAFE_componentWillReceiveProps method invoking setState without any regard from the previous state / props or input contents and reimposing defaults.

@mbrn mbrn self-assigned this Jan 16, 2019
@mbrn mbrn added the bug Something isn't working label Jan 16, 2019
@mbrn
Copy link
Owner

mbrn commented Jan 16, 2019

Hi @martindeanlund ,

I will look at it asap.

@mbrn
Copy link
Owner

mbrn commented Jan 23, 2019

MaterialTable store sorting, filtering and other values of every column on columnDefinition. If you send columns as renewed every time it will be resetted. So try giving columns array to columns from state of your component instead of giving [array] directly.

@mbrn mbrn closed this as completed in a81c48c Jan 23, 2019
@crewtaylor
Copy link

MaterialTable store sorting, filtering and other values of every column on columnDefinition. If you send columns as renewed every time it will be resetted. So try giving columns array to columns from state of your component instead of giving [array] directly.

Can you explain this more. I am confused by what "column" means above.

I have an array that I pass into the data prop of MaterialTable and when ever I change the state of that array it resets all filters. How can I avoid the resetting of the filters?

@mbrn
Copy link
Owner

mbrn commented Jun 14, 2019

Do not send column directly to table. Set your columns array in your components state. Then give this state variable to table.

state = {
 columns: [...]
}

render() {
 <MaterialTable columns={this.state.columns}(/>
}

@dz0l038
Copy link

dz0l038 commented Sep 22, 2020

Hi @mbrn,
Thanks for your solution.
However when I am trying it I still don't manage to obtain the expected result. The filter is indeed not reset, but the data inside the table is not updated anymore. To be more specific, some cells should have their style updated but nothing is happening. Like this one where the cell's color could be updated by the parent:

{
     title: 'Staff',
     field: 'staffUserName',
     render: rowData => {
         const color = rowData.staffColor
         return (
                  <div style={{ backgroundColor: color }}>
                    {rowData.staffUserName}
                  </div>
        )
    },
}

Any guess or workaround?
Cheers

@johnjayasingh
Copy link

@dz0l038 You need to set the columns to state at the time of setting the state. try both before and after updating the rows data.

@dz0l038
Copy link

dz0l038 commented Nov 10, 2020

@johnjayasingh thanks for your comment and sorry for my late reply. Unfortunately, it didn’t solve my issue (or maybe I didn’t understand your solution), the filter was updated but not the content. I get it working anyway so here is my solution, maybe it could help someone in the future.

First, to be clear about what I was trying to achieve:

  • My table component receive data from the parent
  • This data is dynamic and can be updated at any time
  • The user can filter on columns
  • When the data is updated, I want DON’T want the filter to be cleared
  • When the data is updated, I DO want the current filter to be reapply to the updated data

The default behavior of material table is to have the filter cleared at data update, and if I set columns in a state, the content is not updated and filtered based on the new data.

My solution is to use ref as follow:

import React, { useRef } from "react"
import MaterialTable, { MTableBody } from 'material-table'


const ListAssignation = (props) => {
    let filterRef = useRef("")

    const assignToUser = async (rowsSelected) => {
        // Do some action here that update your data
    }

    const unassignTask = async (rowsSelected) => {
        // Do some action here that update your data
    }

    return (
        <MaterialTable
            components={{
                Body: props => <MTableBody {...props} onFilterChanged={(columnId, value) => {
                    props.onFilterChanged(columnId, value);
                    filterRef.current = value
                }} />
            }}
            columns={[
                {
                    title: 'Staff',
                    field: 'staffColumnName',
                    defaultFilter: filterRef.current,
                    render: rowData => {
                        const color = rowData.staffColor
                        return (
                            <div style={{ backgroundColor: color }}>
                                {rowData.staffColumnName}
                            </div>
                        )
                    },
                }
            ]}
            actions={[
                {
                    icon: 'add',
                    tooltip: 'Assign',
                    onClick: (event, rowSelected) => {
                        assignToUser(rowSelected);
                    },
                },
                {
                    icon: 'remove',
                    tooltip: 'Unassign',
                    onClick: (event, rowSelected) => {
                        unassignTask(rowSelected);
                    },
                },
            ]}
            options={{
                actionsColumnIndex: -1,
                selection: true,
                filtering: true,
            }}
            data={props.listTasks}
            title=""
        />
    )
}

export default ListAssignation

@vzdravkovic
Copy link

vzdravkovic commented Feb 11, 2021

Do not send column directly to table. Set your columns array in your components state. Then give this state variable to table.

state = {
 columns: [...]
}

render() {
 <MaterialTable columns={this.state.columns}(/>
}

Is there an alternative for functional components?
The issue im having is if I pass the state to columns using the useState hook i get this error:

Cannot assign to read only property 'tableData' of object '#'

This would mean that I would need to clone the state in order to make the object editable. But if I do so then the columns that are passed are considered new on each render and the filters are reset. Which of course was the reason for putting the columns into state in the first place.

Is there another way of preventing the rerender?

Thank you so much for your support and the great work you're doing. I would really love if I could find a solution.

@elettrodue
Copy link

I have the same issue, when I filter the table and then open a modal changing a state of the component, the table's filters resettings. I use hooks ( a functional component) and if i put the colums array in useState hook whole app crashes

FalkF pushed a commit to FalkF/material-table that referenced this issue May 28, 2021
@jerohero
Copy link

jerohero commented Feb 15, 2022

Had the same issue with the application crashing when I put the columns array in a useState hook. I solved this by specifying the type of the state as a Column array, imported from material-table.

import MaterialTable, { Column } from 'material-table'

const [columns, setColumns] = useState<Column<object>[]>([...])

Note that this is done with TypeScript React.

@adityakabu24
Copy link

I have the same issue, when I filter the table and then open a modal changing a state of the component, the table's filters resettings. I use hooks ( a functional component) and if i put the colums array in useState hook whole app crashes

Any resolutions to this?

@bkorumaz
Copy link

Having a similar problem. rowData prop of editComponent has reset after any state change within the component

@ibr4qr
Copy link

ibr4qr commented Sep 13, 2022

Having a similar problem. rowData prop of editComponent has reset after any state change within the component

What version of material-table are you experiencing this issue??

Put in more information.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests