gargroh / react-table-plugins

This contains miscellaneous react-table v7 plugins
MIT License
92 stars 21 forks source link

useCellRangeSelection fails with virtualization #22

Open danvln opened 3 years ago

danvln commented 3 years ago

Hey,

First of all, this is a great hook! Thanks for providing it - all the appreciation for your work.

I tried the useCellRangeSelection with virtualization, I have enabled in my POC project both: react-window and react-virtual, but for both of them the hook is failing.

Error details:

Error: React Table: startCellId and endCellId has to be valid cell Id

Code path:

// Returns all cells between Range ( between startcell and endcell Ids) const getCellsBetweenId = React.useCallback( (startCell, endCell) => { if (!cellsById[startCell] || !cellsById[endCell]) { console.info({ startCell, endCell }) throw new Error( React Table: startCellId and endCellId has to be valid cell Id ) }

I was expecting the cells to be used from the object that's still in memory and not from the rendering objects that are dropped. But since I am new to these hooks I might miss something.

Thanks again.

gargroh commented 3 years ago

Glad, anyone asked about it, so one of the reason for this can be cell ids are assigned in prepareRow which when virtualizing can skip for some rows but in getCellsBetweenId they are required. To fix this, cell id dependency has to be removed from getCellsBetweenId with some other logic, i will have a look at this..

danvln commented 3 years ago

Thank you, Rohit. I will keep following if there is any update on this; and I can take a deeper look into the code and we can discuss solutions over the weekend. Glad to see your quick response. Also, sorry for opening a duplicate issue. GitHub did a timeout on first, but it looks that it opened it.

Tozzy-dev commented 2 years ago

Hello, sorry to reopen the topic. I'm trying to use the plugin as well and I'm having trouble. The problem comes from the cellsById instance which when initializing the table is empty. Have you encountered this problem? Can you help me ?

vzherebetskyi commented 3 months ago

Just if this is still on the table. If you need useRangeSelection to work with virtualization, here is the code.

Just replace getCellsBetweenId with this function. Kudos to @gargroh for prompt on removing cellsById dependency

 const getCellsBetweenId = React.useCallback(
    (startCell: string, endCell: string) => {
      const updatedRows = rows.map((el, idx) => ({ ...el, index: idx }));

      const startCellPosition = updatedRows.findIndex((el) => startCell.includes(el.id));
      const endCellPosition = updatedRows.findIndex((el) => endCell.includes(el.id));

      if (startCellPosition === -1 || endCellPosition === -1) {
        throw new Error(`React Table: startCellId and endCellId has to be valid cell Id`);
      }

      const rowsIndex = [startCellPosition, endCellPosition];

      const columnsIndex: number[] = [];
      allColumns.forEach((col, index) => {
        if (startCell.includes(col.id)) {
          columnsIndex.push(index);
        }
      });

      const selectedColumns = [];
      const selectedRows = [];
      for (let i = Math.min(...columnsIndex); i <= Math.max(...columnsIndex); i++) {
        selectedColumns.push(allColumns[i].id);
      }
      for (let i = 0; i <= updatedRows.length - 1; i++) {
        if (updatedRows[i].index >= Math.min(...rowsIndex) && updatedRows[i].index <= Math.max(...rowsIndex)) {
          selectedRows.push(updatedRows[i].id);
        }

        if (updatedRows[i].index === Math.max(...rowsIndex)) break;
      }

      const cellsBetween: { [keys: string]: boolean } = {};

      if (selectedRows.length && selectedColumns.length) {
        for (const item of selectedRows) {
          for (const item1 of selectedColumns) {
            const id = item1 + cellIdSplitBy + item;
            cellsBetween[id] = true;
          }
        }
      }

      return cellsBetween;
    },
    [allColumns, cellIdSplitBy, rows],
  );