Version 2 changes
See original GitHub issueThis is an umbrella issue to share my plans for the upcoming version 2.0 release of react-window
.
Feedback is appreciated and will be taken into consideration. I ask that you be understanding if I’m not able to accommodate all requests. I’ll try to do my best to weigh feature requests against bundle size, runtime performance, and maintenance concerns.
I expect that upgrading from version 1 to 2 may require substantial code changes, many of which will not be possible to automate with code mods. Because of this, particularly for application code, I would advise against upgrading existing code unless you have a strong reason (e.g. you need support for dynamic size content).
I am also going to go ahead and pin the current docs to the domain react-window-v1.now.sh so they will not be lost when I update for version 2.
Table of contents:
- Support fewer components
- Use render props API
- No more horizontal lists support
- Only grids support RTL
- Changes to
onScroll
callback timing - Other changes/deprecations
Fewer components
One way to help manage complexity is to reduce the number of components the library supports. I am currently planning on supporting only the following component types in version 2:
SimpleList
(previouslyFixedSizeList
)- This highly optimized list component should be used when row heights are fixed (and known ahead of time).
List
(previouslyDynamicSizeList
)- This list should be used for dynamically sized content (e.g. chat, newsfeed). It requires the
ResizeObserver
API (or polyfill).
- This list should be used for dynamically sized content (e.g. chat, newsfeed). It requires the
Grid
(previouslyVariableSizeGrid
)- This component should be used for tabular data (e.g. spreadsheets) that should be virtualized along both vertical and horizontal axis. It supports variable size rows and columns, but does not support automatically measuring and updating their sizes.
Render props
One of the major changes from react-virtualized
to react-window
was the decision to treat children
as React elements (e.g. React.createElement(children, props))
) rather than as render props (e.g. children(props)
).
There were a couple of motivations for doing this:
- React provides built-in solutions for memoization (e.g.
React.memo
,useMemo
,shouldComponentUpdate
) so I didn’t need to implement my own caching abstraction for item renderers. - APIs like hooks and suspense “just work” inside of item renderers.
- Keys can be managed by
react-window
without requiring the render prop to pass them along (and without requiringcloneElement
calls).
Unfortunately there were also some downsides:
- Inline item renderers incur a high cost. Because their “type” (the function definition) gets recreated each time the parent component renders, React deeply unmounts and remounts their rendered tree. This means that docs need to teach people not to use them even though they’re often more convenient.
- Because inline functions couldn’t be used to close over local scope, it was more complicated for item renderers to share state with parents, requiring APIs like
itemData
and a customareEqual
comparison export.
After taking the above pros and cons into consideration, I’ve decided to convert to a render props approach for react-window
as well. This means that complicated examples like this can be re-written more easily:
const Example = ({ height, items, toggleItemActive, width }) => (
<List
height={height}
itemCount={items.length}
itemRenderer={({ index, key, style }) => {
const item = items[index];
return (
<div key={key} onClick={() => toggleItemActive(index)} style={style}>
{item.label} is {item.isActive ? "active" : "inactive"}
</div>
);
}}
itemSize={35}
width={width}
/>
);
No more horizontal list support
Previously, list components supported both horizontal and vertical layout modes. In order to simplify implementation and maintenance, and because the overwhelmingly common use case is vertical lists, I will be removing support for layout="horizontal"
.
RTL support
Grid components will continue to support direction="RTL"
, but lists will not (since they will only support a vertical layout). This tradeoff is being made to enable lists to be smaller and easier to maintain.
onItemsRendered
and onScroll
callback changes
List and grid components currently support onItemsRendered
and onScroll
callback props. These callbacks are called during the commit phase (after the list or grid has completed rendering). This can be useful in that it is always safe to perform a side effect (like analytics logging) in response to these callbacks, but it has a downside as well: any scroll synchronized updates must be done in a second (“cascading”) render.
Version 2 will make a change to the onScroll
callback to address this. The onScroll
callback will be called during the event’s dispatch cycle so that any update will be batched (by React) with the list or grid’s own update.
The onItemsRendered
callback will be replaced with a onItemsDisplayed
prop, although it will continue to be called during the commit cycle. This change is being made to enable the list component to more aggressively optimize render performance by pre-rendering at idle priority and make use of experimental APIs like display locking.
Other props changes/deprecations
There are several pending deprecations (with DEV warnings) which will be removed:
innerTagName
andouterTagName
for all list and grid components. (UseinnerElementType
andouterElementType
instead.)overscanCount
,overscanColumnsCount
, andoverscanRowsCount
for grid component. (UseoverscanColumnCount
andoverscanRowCount
instead.)overscanCount
will be removed for list components, in favor of a dynamic overscanning approach.- “horizontal” and “vertical” values for
direction
. (These were moved tolayout
, but they will be removed entirely in version 2.) - The
itemData
prop (and the correspondingdata
prop passed to item renderers) will be removed because the change to a render prop API no longer make this necessary. - The
useIsScrolling
prop (and the correspondingisScrolling
prop passed to item renderers) will be removed because the changes to pre-rendering and display locking would make this more expensive to implement. - Scroll align parameters will change slightly. The previously named “auto” will now be named “minimal”. The new default value will be “smart” (rather than “auto”).
Note that some of the above deprecated props may not still be relevant given the other planned changes, but I’m listing them here anyway for completeness sake.
Issue Analytics
- State:
- Created 4 years ago
- Reactions:115
- Comments:46 (14 by maintainers)
Top GitHub Comments
Horizontal lists are widely used on mobile in our case. We are use them for infinite scrollable carousel like control too. IMO must have thing on mobile.
I have accepted the fact that I don’t have the time or energy to finish this effort. If anyone would like to step in and finish the branch I started, I’d welcome your help. (Please also see issue #6 for details on the
List
andGrid
should be implemented to support just-in-time measurements.)