@bestyled/contrib-flatlist
Version:
Implementation of FlatList for the BeStyled Design System
80 lines (62 loc) • 8.17 kB
Markdown
# bestyled/flatlist
A performant, infinite, virtualized list for React. See `react-virtualized`, `react-window` and `react-tiny-virtual-list` for prior art; this package is designed to
- Be extremely fast, with fine grained use of React Hooks (16.8+) instead of the less granular PureComponent used by existing solutions
- Delegate absolution positioning to the browser with use of FlexBox layout (removes need for `top` / `size` styles on every element, as we simply observe what the browser does and then size the outer container accordingly)
- Assumes variable size vertical items by default, with auto-resizing whenever the layout changes; if you want a FixedSizeList or Grid you may want to stick with `react-window`
- Avoid dependencies on CellMeasurer and other techniques to pre-determine height of every item and instead build right in using a very simple react hook for ResizeObserver (polyfilled using react-resize-observer)
- Support scrolling to Index without calculating the size of all intermediate entries, particularly useful for Scroll-To-End based conversational user interfaces
- Removes advanced APIs like sticky index and sticks to the absolute minimum required to run a variable dynamic list
Unlike just about all other implemetations of virtualized lists for React, no old-school React Components inside, with just one code file for the Functional Component and one file for the Size and Position state manager.
## Example Usage
```ts
import React from 'react'
import { render } from 'react-dom'
import { FlatList } from '@bestyled/contrib-flatlist'
import { AutoSizer } from '@bestyled/contrib-common'
// kick off the smoothscroll polyfill (for Safari, etc.)
import smoothscroll from 'smoothscroll-polyfill'
smoothscroll.polyfill()
const listItems = items.map((item, index) => (
<React.Fragment key={index}>
<RowHeader date={item.header} />
<RowCard item={item} />
</React.Fragment>
))
const renderRow = ({ index }) => {
return listItems[index]
}
render(
<AutoSizer flex={1} my={3}>
{({ height }) => (
<List
estimatedItemSize={100}
height={height}
itemCount={listItems.length}
scrollToIndex={listItems.length - 1}
scrollToAlignment="end"
renderItem={renderRow}
/>
)}
</AutoSizer>
)
```
### Prop Types
| Property | Type | Required? | Description |
| :---------------- | :----------------- | :-------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| height | Number \| String\* | ✓ | Height of List. This property will determine the number of rendered items. |
| itemCount | Number | ✓ | The number of items you want to render |
| renderItem | Function | ✓ | Responsible for rendering an item given it's index: `({index: number}): React.PropTypes.node`. The returned element must handle the given item key; any styling is up to you. |
| scrollToIndex | Number | | Item index to scroll to (by forcefully scrolling if necessary) x |
| scrollToAlignment | String | | Used in combination with `scrollToIndex`, this prop controls the alignment of the scrolled to item. One of: `'start'`, `'center'`, `'end'` or `'auto'`. Use `'start'` to always align items to the top of the container and `'end'` to align them bottom. Use `'center`' to align them in the middle of the container. `'auto'` scrolls the least amount possible to ensure that the specified `scrollToIndex` item is fully visible. |
| stickyIndices | Number[] | | An array of indexes (eg. `[0, 10, 25, 30]`) to make certain items in the list sticky (`position: sticky`) |
| overscanCount | Number | | Number of extra buffer items to render above/below the visible items. Tweaking this can help reduce scroll flickering on certain browsers/devices. |
| estimatedItemSize | Number | | Used to estimate the total size of the list before all of its items have actually been measured. The estimated total height is progressively adjusted as items are rendered. |
| onScroll | Function | | Callback invoked whenever the scroll offset changes within the inner scrollable region. It has the following signature: `(scrollTop: number, event: React.UIEvent<HTMLDivElement>)`. |
## Dependencies
Three standalone React Hooks are used from `@bestyled/contrib-common`. These could easily be incorporated yourself to eliminate this dependency. One of these has an additional depdency on `ResizeObserver` polyfill
- useResizeObserver - simple wrapper around ResizeObserver to be notified whenever an element size has been changed
- useForceUpdate - convenience method to force a state change
- useInstanceRef - convenience method to lazy initialize an instance reference
Peer dependency on `smoothscroll-polyfill` and `react`
## License
Apache 2.0