Jstuff
Jstuff

Reputation: 1344

Use state variable in ag grid callback not updating

My use state variable, query, inside of the function isExternalFilterPresent never updates. I'm perplexed because the first console.log of query updates with each change of query. I think this is because I'm not quite understand the implementation of hooks.

let gridApi: GridApi | null = null;

const HouseholdTable = ({accountsData, aggregateEntityTable: {aggregateEntity, columnDefs}}: OwnProps & StateProps) => {

  const [isDeepDiveOpen, setIsDeepDiveOpen] = useState(false);
  const [query, setQuery] = useState('');

  useEffect(() => {
    gridApi && gridApi.onFilterChanged();
  }, [query]);

  if (accountsData) {

    const onGridReady = ({api}: GridReadyEvent) => {
      api.sizeColumnsToFit();
      gridApi = api;
    };

    const aggData = accountsData.aggregations[aggregateEntity];

    console.log(query); // This updates when query changes
    const isExternalFilterPresent = (): boolean => {
      console.log(query); // This never updates
      return !!query; 
    };

    const doesExternalFilterPass = (rowNode: RowNode): boolean => {
      // console.log('doesExternalFilterPass');
      return true;
    };

    return (
      <>
        <HouseholdsToolbar aggData={aggData}
          isDeepDiveOpen={isDeepDiveOpen}
          onDeepDiveToggleClick={setIsDeepDiveOpen}
          onQueryChange={setQuery}
        />
        <AgGridReact rowData={[]}
          columnDefs={[]}
          gridOptions={{
            headerHeight: 70,
            suppressFieldDotNotation: true,
            suppressHorizontalScroll: false,
            onGridReady,
            isExternalFilterPresent,
            doesExternalFilterPass
          }}
        />
      </>
    );
  } else {
    // handle loading
    return (<div>loading</div>);
  }
};

const mapStateToProps = (state: StoreState): StateProps => {
  const {faStore: {accountsData}} = state;
  return {
    accountsData,
    aggregateEntityTable: aggregateEntityTableDummyConfig
  };
};

export default connect(mapStateToProps)(HouseholdTable);

export const aggregateEntityTableDummyConfig: AggregateEntityTable = {
  aggregateEntity: 'FOO',
  columnDefs: []
};

EDIT: Updated with the entire component.

Upvotes: 5

Views: 3608

Answers (1)

Andrii Golubenko
Andrii Golubenko

Reputation: 5179

It is not a problem with hooks. It looks like on the first rendering AgGridReact stores the reference to a function that you pass to isExternalFilterPresent and then never changes this reference on re-renders. To be more clear, AgGridReact stores the first 'version' of isExternalFilterPresent and never updates it. To fix your problem, you need to store the value of your filter in useRef hook.

React doc says:

The useRef() Hook isn’t just for DOM refs. The “ref” object is a generic container whose current property is mutable and can hold any value, similar to an instance property on a class.

So you might think about useRef like about property in the class.

Here what you have to do:

const query = useRef(null);

const setQuery = (value) => {
  query.current = value;
  gridApi && gridApi.onFilterChanged();
}

const isExternalFilterPresent = (): boolean => {
  console.log(query.current); // Now it changes
  return !!query.current; 
};

Here an example on codesandbox

Upvotes: 11

Related Questions