Super Simple List Virtualization in React with IntersectionObserver

Want smoother scrolling, but having trouble getting react-virtualized or react-window to work in your app? Try this dead-simple drop-in virtualization technique instead.

Want that smooth scrolling on your lists? Read on!

Some quick background

The standard solutions

Enter IntersectionObserver

The joy of simple lazy rendering

Where can I get it?

npm install react-render-if-visible --save
yarn add react-render-if-visible

Show me under the hood!

import React, { useState, useRef, useEffect } from 'react'

const isServer = typeof window === 'undefined'

type Props = {
defaultHeight?: number
visibleOffset?: number
root?: HTMLElement
}

const RenderIfVisible: React.FC<Props> = ({
defaultHeight = 300,
visibleOffset = 1000,
root = null,
children
}) => {
const [isVisible, setIsVisible] = useState<boolean>(isServer)
const placeholderHeight = useRef<number>(defaultHeight)
const intersectionRef = useRef<HTMLDivElement>()

// Set visibility with intersection observer
useEffect(() => {
if (intersectionRef.current) {
const observer = new IntersectionObserver(
entries => {
if (typeof window !== undefined && window.requestIdleCallback) {
window.requestIdleCallback(
() => setIsVisible(entries[0].isIntersecting),
{
timeout: 600
}
)
} else {
setIsVisible(entries[0].isIntersecting)
}
},
{ root, rootMargin: `${visibleOffset}px 0px ${visibleOffset}px 0px` }
)
observer.observe(intersectionRef.current)
return () => {
if (intersectionRef.current) {
observer.unobserve(intersectionRef.current)
}
}
}
}, [intersectionRef])

// Set height after render
useEffect(() => {
if (intersectionRef.current && isVisible) {
placeholderHeight.current = intersectionRef.current.offsetHeight
}
}, [isVisible, intersectionRef])

return (
<div ref={intersectionRef}>
{isVisible ? (
<>{children}</>
) : (
<div style={{ height: placeholderHeight.current }} />
)}
</div>
)
}

export default RenderIfVisible

Results from use in production

What about those drawbacks?

Conclusion

Founder at NightCafe Studio, COO at BrainBlocks

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store