primereact icon indicating copy to clipboard operation
primereact copied to clipboard

DataTable: [Violation] 'input' handler took <N>ms

Open Nessario opened this issue 1 year ago • 1 comments

Describe the bug

I have a use case for the DataTable which seems to be hitting some limits of the component.

My use case is that I have a table with 38 columns, which has thousands of entries hence it's connected with the back-end API to do the pagination and filtering.

We make use of PrimeReact filter UI with filterDisplay set to menu, now when trying to input a certain value in any of the one columns, the input handler takes time to take place, usually it's about 500ms for a simple input change. Which shows with this error: [Violation] 'input' handler took 528ms

Also, when the table first renders it shows similar messages but for different handlers, which are:

[Violation] 'setTimeout' handler took 545ms [Violation] 'message' handler took 492ms

When I'm running the profiler to find the bottleneck, I see that for each input change the whole table gets re-rendered. I think it's best to not trigger a full re-render until the Apply is clicked. That is one assumption that I have, if there is an option that I'm missing please let me know.

Reproducer

No response

System Information

System:
    OS: macOS 12.5.1
    CPU: (10) x64 Apple M1 Pro
    Memory: 21.35 MB / 16.00 GB
    Shell: 5.8.1 - /bin/zsh
  Binaries:
    Node: 22.2.0 - ~/.nvm/versions/node/v22.2.0/bin/node
    npm: 10.7.0 - ~/.nvm/versions/node/v22.2.0/bin/npm
    pnpm: 9.11.0 - ~/Desktop/**/node_modules/.bin/pnpm
  Browsers:
    Chrome: 129.0.6668.101
    Safari: 15.6.1
  npmPackages:
    primereact: ^10.8.2 => 10.8.3 
    react: ^18.3.1 => 18.3.1 
    tailwindcss: ^3.4.10 => 3.4.13

Steps to reproduce the behavior

  1. Make use of DataTable component
  2. Have a list with 38 columns and thousands of entries
  3. Map that data as below:
<DataTable
  stripedRows
  showGridlines
  rowHover
  lazy
  scrollable
  resizableColumns
  rows={meta?.per_page}
  totalRecords={meta?.total}
  paginator
  paginatorPosition="top"
  paginatorTemplate={paginatorTemplate}
  columnResizeMode="expand"
  scrollHeight="700px"
  reorderableColumns
  value={data}
  filterDisplay="menu"
  size="small"
  first={meta?.from}
  tableStyle={{ tableLayout: 'fixed' }}
  filters={tableFilters}
  onColReorder={onColReorder}
  onPage={onPage}
  onFilter={onFilter}
>
  {visibleColumns.map((col) => (
    <Column
      key={`${col.field}-${name}`}
      field={col.field}
      columnKey={col.field}
      filter={col.filter}
      body={(rowData: D, options) => customBodyTemplate(rowData, options, col.body)}
      header={col.header}
      filterField={col.field}
      filterElement={col.filterElement}
      expander={col.expander}
      style={{ width: '240px' }}
      headerStyle={{ width: '240px' }}
      bodyStyle={{ width: '240px' }}
    />
  ))}

  {actionButtons && (
    <Column body={actionButtons} header="Aktionen" exportable={false} style={{ width: '8rem' }} />
  )}
</DataTable>

### Expected behavior

All the handlers should be handled in an optimal way so large data sets don't get impacted.

Nessario avatar Oct 18 '24 10:10 Nessario

Most likely related to https://github.com/primefaces/primereact/issues/6811

melloware avatar Oct 18 '24 12:10 melloware

EDIT: I solved it by creating my own filter and instead of using onChange, I used onBlur

const filterString= (opt: ColumnFilterElementTemplateOptions) => {
    return (
        <InputText
            defaultValue={opt.value}
            onBlur={(e) => opt.filterCallback(e.currentTarget.value)}
        />
    );
};
 <Column filterElement={filterString)} />

This is just an example, you must set up a filter of the ideal type for your column type

B-Schmitz avatar Jan 22 '25 14:01 B-Schmitz