If you need to show many list items, one common technique to overcome this issue, is to apply the concept of “virtual scrolling”.
You only render visible items on the page, and a few more to pre-load them.
This makes the experience “infinite” and smooth.
React library
Looking through GitHub and NPM I found react-tiny-virtual-list.
Install the library with
npm install react-tiny-virtual-list
Then I used it this way:
import VirtualList from 'react-tiny-virtual-list';
const Timeline = (props) => {
render (props) {
const timeline = (props.timeline || [])
.filter(t => retweets ? true : !t.retweet)
.filter(t => replies ? true : !t.reply)
...
return (
<VirtualList
width='100%'
height='100vh'
itemCount={timeline.length}
itemSize={(i => {
const item = timeline[i]
const text = item.formatted || item.text || '\n'
const newLinesCount = text.split('\n').length
return 200 + newLinesCount * 15 + text.length * 0.3
})}
overscanCount={10}
renderItem={({ index, style, t = timeline[index] }) =>
<div id={`t${+new Date(t.date)}`} tabIndex={index + 2} key={index} style={style} class={timelineStyles.tweet + ' p-0 border-0 py-5'}>
<div class=''>
<small class=''><a href={t.link} tabIndex={-1} target='_blank' rel='noopener noreferrer'>{new Date(t.date).toISOString().substring(11, 16)}</a></small>
<h5 class=''>
<div style={`background-size: contain; background-image: url(${t.authorAvatar})`} />
{t.author}
</h5>
<span class=''><p>{t.date}</p></span>
</div>
<p class=''><Linkify>{t.formatted || t.text}</Linkify></p>
</div>}
/>
)
}
}
This achieves the following:
- a list of items (with 10 overscan)
- dynamic
itemSize
based on text and content length
I think this is beautifully simple, especially performant!
Seamless integration with Preact
Yes!
If you’re using the preact-cli, or configured your bundler accordingly, you have support for preact/compat
built in.
Which makes this a performance improvement without heavy shimming or other fluff.