title: Ag-Grid, React, Redux Filters Issue - can not set setFilterModel()
body: <p>Here is my scenario,
  I am making a <code>onFetchEvents</code> Redux Action call and getting all events and passing it as follows. <code>rowData={this.props.events.data}</code></p>
  
  <p>Everything works fine. Now I need to apply a filter, and this requires another call to the server.</p>
  
  <p>I set <code>enableServerSideFilter: true,</code> so that when a filter applied, datagrid does not make a call on its own.</p>
  
  <p>I monitor filter changes and call <code>handleFilterChanged</code>. I get the <code>const filterModel = this.gridApi.getFilterModel();</code> and send it to rest endpoint.</p>
  
  <p>Everything works fine but the datagrid does not remember the filter state. </p>
  
  <p>I tried <code>this.gridApi.setFilterModel(filterModel);</code> but it gets me into infinite loop.</p>
  
  <p>To make the long story short, how can I use filters with Redux so that I have full control also where should I use <code>this.gridApi.setFilterModel()</code></p>
  
  <p>Let me know if you need more clarification.</p>
  
  <p>Thanks</p>
  
  <pre><code>    /* eslint-disable */
      import React, { Component, Fragment } from 'react';
      import { connect } from 'react-redux';
      import { AgGridReact } from 'ag-grid-react';
      import { fetchEvents } from '@mc/duck/actions/AppActions';
      import 'ag-grid-enterprise';
      import 'ag-grid-community/dist/styles/ag-grid.css';
      import 'ag-grid-community/dist/styles/ag-theme-balham-dark.css';
      // import './customTheme.scss';
  
      // col resizing pipe is not visibles
      class DatagridPage extends Component {
        constructor(props) {
          super(props);
          this.state = {
            params: {
              filterModel: {},
              page: 1,
              limit: 10,
            },
            gridOptions: {
              enableServerSideFilter: true,
              enableSorting: true,
              enableColResize: true,
              suppressMenuHide: true,
              pagination: true,
              animateRows: true,
              onFilterChanged: this.handleFilterChanged,
              onSortChanged: () =&gt; console.log('onSortChanged'),
              columnDefs: [
                {
                  headerName: 'id',
                  field: 'id',
                  headerClass: 'test',
                  checkboxSelection: true,
                  filter: 'agTextColumnFilter',
                },
                {
                  headerName: 'name',
                  field: 'name',
                  headerClass: 'test',
                  filter: 'agTextColumnFilter',
                },
                {
                  headerName: 'risk score',
                  field: 'risk_score',
                  headerClass: 'test',
                  filter: 'agTextColumnFilter',
                },
                {
                  headerName: 'urgency',
                  field: 'urgency',
                  headerClass: 'test',
                  filter: 'agTextColumnFilter',
                },
                { headerName: 'type', field: 'type', headerClass: 'test', filter: 'agTextColumnFilter' },
                {
                  headerName: 'artifacts',
                  field: 'artifacts',
                  headerClass: 'test',
                  filter: 'agTextColumnFilter',
                },
                {
                  headerName: 'created',
                  field: 'created',
                  headerClass: 'test',
                  filter: 'agTextColumnFilter',
                },
                {
                  headerName: 'updated',
                  field: 'updated',
                  headerClass: 'test',
                  filter: 'agTextColumnFilter',
                },
                { headerName: 'due', field: 'due', headerClass: 'test', filter: 'agTextColumnFilter' },
                {
                  headerName: 'owner',
                  field: 'owner',
                  headerClass: 'test',
                  filter: 'agTextColumnFilter',
                },
                {
                  headerName: 'status',
                  field: 'status',
                  headerClass: 'test',
                  filter: 'agTextColumnFilter',
                },
                {
                  headerName: 'description',
                  field: 'description',
                  headerClass: 'test',
                  filter: 'agTextColumnFilter',
                },
              ],
            },
          };
        }
  
        componentDidMount() {
          console.log('componentDidMount');
          const { params } = this.state;
          this.props.onFetchEvents(params);
        }
  
        onGridReady = params =&gt; {
          this.gridApi = params.api;
          this.gridColumnApi = params.columnApi;
          this.gridApi.sizeColumnsToFit();
          console.log('onGridReady', this.gridApi.getFilterModel());
        };
  
        onPageSizeChanged(newPageSize) {
          var value = document.getElementById('page-size').value;
          const paramsCopy = { ...this.state.params };
          paramsCopy.limit = Number(value);
          paramsCopy.page = 1;
          this.setState({ params: paramsCopy }, () =&gt; this.props.onFetchEvents(paramsCopy));
          this.gridApi.paginationSetPageSize(Number(value));
        }
  
        handleFilterChanged = () =&gt; {
          console.log('handleFilterChanged');
          const filterModel = this.gridApi.getFilterModel();
          const paramsCopy = { ...this.state.params, filterModel };
          console.group('handleFilterChanged');
          console.log('filterModel', filterModel);
          console.log('state filterModel', this.state.params.filterModel);
          if (!areEqualShallow(filterModel, this.state.params.filterModel)) {
            this.gridApi.setFilterModel(filterModel);
            this.setState({ params: paramsCopy }, () =&gt; this.props.onFetchEvents(paramsCopy));
          }
          console.groupEnd();
  
          function areEqualShallow(a, b) {
            for (var key in a) {
              if (!(key in b) || a[key] !== b[key]) {
                return false;
              }
            }
            for (var key in b) {
              if (!(key in a) || a[key] !== b[key]) {
                return false;
              }
            }
            return true;
          }
          // this.gridApi.setFilterModel(filterModel);
        };
  
        render() {
          return (
            &lt;Fragment&gt;
              &lt;div&gt;
                Page Size:
                &lt;select onChange={this.onPageSizeChanged.bind(this)} id="page-size"&gt;
                  &lt;option value="10"&gt;10&lt;/option&gt;
                  &lt;option value="100"&gt;100&lt;/option&gt;
                  &lt;option value="500"&gt;500&lt;/option&gt;
                  &lt;option value="1000"&gt;1000&lt;/option&gt;
                &lt;/select&gt;
              &lt;/div&gt;
              &lt;div
                className="ag-theme-balham-dark"
                style={{
                  height: '500px',
                  width: '100%',
                }}
              &gt;
                &lt;AgGridReact
                  rowSelection="multiple"
                  gridOptions={this.state.gridOptions}
                  columnDefs={this.state.columnDefs}
                  rowData={this.props.events.data}
                  defaultColDef={this.state.defaultColDef}
                  onGridReady={this.onGridReady}
                  rowHeight={49}
                /&gt;
              &lt;/div&gt;
            &lt;/Fragment&gt;
          );
        }
      }
  
      const mapStateToProps = state =&gt; ({
        events: state.app.events,
      });
  
      const mapDispatchToProps = {
        onFetchEvents: params =&gt; fetchEvents(params),
      };
  
      export default connect(
        mapStateToProps,
        mapDispatchToProps,
      )(DatagridPage);
  </code></pre>