Version 8 Roadmap
See original GitHub issueI have begun working on react-virtualized
version 8 (see PR #387). This issue outlines my intended changes. I welcome input from the community- so please feel free to comment below if you think certain features should (or should not) be included in the next upcoming major release.
Upgrade instructions and jscodeshift mods are available here.
High level goals
- Improve performance, particularly scrolling performance.
- Reduce learning curve; make things simpler for first-time users!
Progress
Planned changes:
- Rename components (
FlexColumn
,FlexTable
,VirtualScroll
) - Remove
.Grid_cell
wrapper<div>
- CSS class names
- All functional styles moved inline
Potential changes:
- More consistent index params
- Measure
CellMeasurer
content within parent component - Support measurement persistence
Planned changes
Rename components
Certain components in react-virtualized
have arbitrary names. For example, VirtualScroll
is ambiguous and FlexTable
is unnecessarily specific. In order to improve the first-time-user experience, version 8 will rename a few components.
Version <= 7 | Version 8+ |
---|---|
FlexColumn |
Column |
FlexTable |
Table |
VirtualScroll |
List |
A codemod is available for this change:
jscodeshift -t /path/to/react-virtualized/codemods/7-to-8/rename-components.js source
Remove .Grid_cell
wrapper <div>
My single biggest focus with recently updates to this library has been improving scrolling performance. Removing unnecessary DOM elements is a win. To this end, version 8 will be removing the cell wrapper and passing style information directly to your cellRenderer
to be used. In other words this:
<div class="Grid__cell" style="left; top; height; width;">
<div class="your-custom-class" style="your-custom-style;">
<!-- Your content -->
</div>
</div>
…will become this:
<div class="your-custom-class" style="position; left; top; height; width; your-custom-style;">
<!-- Your content -->
</div>
This will also enable me to remove the following style-related properties (as you will have full control over the wrapper cell yourself):
Component | Properties to be removed |
---|---|
Grid |
cellClassName , cellStyle |
VirtualScroll |
rowClassName , rowStyle |
FlexTable |
rowWrapperClassName , rowWrapperStyle |
This change also means that your cellRenderer
will be responsible for a few more things. Below is an example of a version 8 cellRenderer
. Note that key
and style
parameters are new:
function cellRenderer ({
columnIndex, // Horizontal (column) index of cell
isScrolling, // The Grid is currently being scrolled
key, // Unique key within array of cells
rowIndex, // Vertical (row) index of cell
style // Style object to be applied to cell
}) {
// Grid data is a 2d array in this example...
const user = list[rowIndex][columnIndex]
// If cell content is complex, consider rendering a lighter-weight placeholder while scrolling.
const content = isScrolling
? '...'
: <User user={user} />
// It is important to attach the style specified as it controls the cell's position.
// You can add additional class names or style properties as you would like.
// Key is also required by React to more efficiently manage the array of cells.
return (
<div
key={key}
style={style}
>
{content}
</div>
)
}
There is no codemod for this change due to its complexity. However you may use the following HOF to maintain backwards compatibility and allow you to migrate cell renderers one at a time.
// Can be used for Grid, List, or Table
function createCellRenderer (cellRenderer) {
return function cellRendererWrapper ({ key, style, ...rest }) {
return (
<div
key={key}
style={style}
>
{cellRenderer(rest)}
</div>
)
}
}
// Demonstrates example usage
function renderGrid (props) {
const { cellRenderer, ...rest } = props
return (
<Grid
cellRenderer={createCellRenderer(cellRenderer)}
{...rest}
/>
)
}
CSS class names
As of this time there is still no single way the community has agreed on regarding styles within React. This is particularly tricky for a library as styling choices can impose constraints on application code. For example if a library component chooses to use inline styles then an application is required to also use inline styles (or the !important
directive) in order to override defaults. Because of this, react-virtualized
will continue to use global/static class names for the time being.
However generic class names like .Grid
(or .List
, .Table
, etc) can also cause complications for application code. To address this, version 8 class names will use a .ReactVirtualized__
prefix. For example, the outer-most class for a Grid
component will be ReactVirtualized__Grid
.
All functional styles moved inline
Collection
, Grid
, and List
used to depend on an external react-virtualized styles.css
file for their static styles. With version 8 this is no longer the case. All functional styles (eg position, overflow, etc) have been converted to inline styles. This means that for many apps- the external stylesheet will no longer be required at all.
Note that the Table
component also includes several presentational styles by default. These will remain in the styles.css
file to enable them to be easier for application code to override.
Potential changes
More consistent index params
Grid
renderers receive 2 properties: columnIndex
and rowIndex
while corresponding VirtualScroll
and FlexTable
methods receive only a single parameter, index
. This is fairly intuitive but it increases the difficulty of creating HOCs that are capable of working with etiher type of component because it requires users to rename/map parameters (eg one({ index }) => two({ columnIndex: 0, rowIndex: index })
).
As of version 8, all 3 components (Grid
, List
, and Table
) will use the more qualified names. Table
will pass a rowIndex
parameter to its children and List
will pass rowIndex
.
Measure CellMeasurer
content within parent component
CellMeasurer
renders its content to a hidden div mounted at the root of the document. This has a couple of drawbacks:
- Rendered content can’t be moved from the document to the (eventual) intended parent and so it must be thrown away and recreated (which is expensive).
- Inherited styles don’t get applied during the first render which can cause the measurements to be inaccurate.
Currently neither Grid
nor CellMeasurer
are aware of each other and so this cannot be avoided. However it should be possible for Grid
(or List
or Table
) to provide a way for CellMeasurer
to render content inside of itself so as to re-use the rendered content for display purposes after it has been measured.
It is possible that this ends up adding more complication than it is worth and this feature gets dropped. It is also possible that I will be able to implement this feature in a way that does not impact the external API.
Support measurement persistence
Issue Analytics
- State:
- Created 7 years ago
- Reactions:33
- Comments:30 (27 by maintainers)
Top GitHub Comments
@nhducit
I recommend using react-draggable for this. Easy to use and works well with react-virtualized. I’ve used this combination myself in production apps it works great. 😄
This is a windowing library. Drag and drop is its own, very large space. However there is a fantastic library by @clauderic called react-sortable-hoc that can be used with react-virtualized for drag-and-drop behavior. I’ve used this myself in production apps and have been very happy with the results. 😁
This has been supported ever since version 1 by the
Grid
component.Sticky columns and rows are possible already using the
ScrollSync
HOC. See a demo here.Cool @bvaughn! I really like the version 8 roadmap 👏
Regarding components naming I have some concerns though. You’re planning to rename
VirtualScroll
toList
and I like the idea, but I’m wondering if this may create some confusion to RV users.List
name is so common that I’ll be a bit hard to differentiate between an app’s component or RV one. Obviously you can infer it taking a look at the props the component receives, but surely it’ll take more time that just looking at the name.I was thinking that maybe using the prefix
Virtual
for all components could be interesting. So this is how it’d look like:Grid
=>VirtualGrid
FlexTable
=>VirtualTable
VirtualScroll
=>VirtualList
Collection
=>VirtualCollection
Though it’s possible to alias all these components when importing, I think this naming it’s more self explanatory. What do you think?