0

Is it possible to use React Virtualized when there is no notion of a row index to get rowdata?

I would like to use React Virtualized to display data coming from a large (100k+ rows) database-table that is constantly being modified: rows are added/deleted/updated at random positions in the table.

I have no function that can get a row by using a row index because the position of every row is changing every few seconds.

The table is sorted and every row is guaranteed to have a unique content, so what I do have are the following functions:

getFirst/LastRow() => data : get the data content for the (currently) first/last row

getNext/PreviousRows(startData, nrRows) => data[] : get the data content for the (currently) next/previous nrRows, starting at row with content startData

findRow(data) => data : find the row that has content data

I also have an observer function that is tracking the table mutations in real-time, so I can get a callback for every insert/delete/update operation for the table.

Is there a way to map these available functions to a workable React Virtualized configuration ?

willemx
  • 530
  • 7
  • 19

2 Answers2

0

Is it possible to use React Virtualized when there is no notion of a row index to get rowdata?

No. Mapping an index (or indices) to data is core to how react-virtualized works. You would need to build/maintain some structure that allowed you to efficiently access data at an index (even if that index frequently changed) in order to benefit from the lib.

When the data changes, every few seconds, is it usually items being appended onto one end of the remote collection? Or could it be resorting, deletions, etc?

The linked-list style API you describe almost seems like it was meant more to work with a pagination control.

bvaughn
  • 13,300
  • 45
  • 46
  • Data changes are mostly updates (that will change the sorting order) and inserts that are generally at a random position in the table (so they will also change the sorting order). Deletes are infrequent. I had hoped that there could be made some method 'recomputeRowIndices' to resync the RV row data to the database table contents whenever there is a change within the rows that are currently managed by RV – willemx Feb 18 '17 at 17:39
  • The current API is indeed being used for pagination control. I wrote some code to make it work with scrolling too, but it's a bit clunky. Using RV would be much nicer. – willemx Feb 18 '17 at 17:47
  • RV generally performs very well, even with a lot of inserts/deletes/sorts. If you write a performant mapping function (turning your linked list style API into a more array-like structure) then you should be fine. :) – bvaughn Feb 18 '17 at 23:30
  • eg if you're doing more expensive things with RV (eg dynamically measuring rows with `CellMeasurer`) then you can configure it to cache measurements by id instead of index. This reduces the impact of inserts/deletes/sorts. – bvaughn Feb 18 '17 at 23:31
0

I think the answer as asked might be "Yes" if the semantics of

to use React Virtualized

can be understood to mean where RV is "a piece of the puzzle". I think this was essentially stated very well and accurately with the opposite answer in terms of RV itself having

no notion of a row index

RV does need to know about its own row indexes. But if RV is implemented, and simply handed data at whatever event interval (i.e. pagination) from a "parent"... it is possible to use RV w/o it having an understanding of the parent's row index being used

to get rowdata

You could think of your paginated app as the parent. The dataGrid component as the child. The state/render cycle in your parent React app just needs to re-render the dataGrid (and it's scroller) at the spot the user will find intuitive in relation to your data "pages".

I've been modeling a similar solution with a different "dataGrid" component, and following various mindshare on the issue. At the risk of [more] tl;dr, my current technique is like this:

  • feed a total rowcount to the dataGrid component, so it sets up as if I'm going to give it the whole api in one un-paginated shot
  • feed only the data from the currently available data page (say 500 records)
  • dataGrid's onScroll event calculates a conditional threshold for me to cross (scrollTop, etc.) indicating that the list has scrolled to the top or bottom row of the current page as my parent application understands it
  • onScroll calculates rows and pages, gets new data, and sets new state
  • new state has the same huge rowcount, but along with different data rows from a API call
  • use should/did update lifecycles in React to:

    1. "scrollTo" and reposition the component grid to whichever row my parent understands as the top of right "page", and
    2. (warning... prototype) I concatenate my paged data array with padding (cringe) like [...Array({#ofRows*#ofpages})].concat(newData), so that the child component leaves the drag handle where the user expects just before I render. Ultimately, I am hoping this will be done by adjusting the height of the top or bottom-most divs in my list to compensate for the intended scrollbar position, but it's an evolving work in its priorities.
  • I've also maybe found a macrocosm of the same issues in my own pagination that the windowing libraries solve with over-scanning rows. It seems I must "overscan" in my API calls, so that I have a buffer outside the windowing component's own top/botom. This may well go away with better logic in the end. Fingers crossed.

References I am finding helpful:

Some more history for the discussion using this library is here.

Also, react-window-paginated looks to have solved the basics of the problem your comments describe using the newer react-window lib. This solution is very compelling to me as a code design of where I might end up in my final composition. RW doesn't leave you with RV's feature set, though, but it's easily extendable and maybe easier to start here if you don't need tons of RV features out of the gate.

If you were to tackle the pagination solution in RV, this might stimulate a prototype, though it does not solve the API pagination or mapping/threading issue itself.

Blaine
  • 1
  • 2