Make a react-window (2)

Outsider987
3 min readApr 30, 2022

--

Previously:

Introduce:

as last time introduce react-window , I had separate the design structure try to understand how it work , and today I’m going use IntersectionObserverEntry to make simliar as react-window List component

List design

Div design:

react-window paremeter is by px , here I want did some different is by hv , that will be more availability on the responsive

  • div1: we need set max height value when child element is over size will show scroll bar
    - max-height: <parameter>by hv
    - overflow: auto
  • div2: here we need set virtual height for scroll bar
    - height: itemCount * rowheight = total height
    - position: relative
  • row div: per row we need give the top height to align and position
    - position: absolute
    - top: by current index
    - className: tr

IntersectionObserverEntry:

we need pass two paremeter to IntersectionObserver

  • option :
const options = {root: document.getElementById('List'),rootMargin: `-${rowHeight}px 0px -${rowHeight}px 0px`,threshold: 0,};
  • callbackFunction :
const Rows = Array.from(Array(itemCount).keys());const currentIndex = useRef(0);let value2 = height / rowheight;value2 += 2;const [maxValue, setMaxValue] = useState(value2);let rowHeight = 0;const elementArrary2 = Array.prototype.slice.call(document.getElementsByClassName('tr')) as HTMLDivElement[];rowHeight = elementArrary2[0].clientHeight;const onEnterView = (entries: IntersectionObserverEntry[], observer: IntersectionObserver) => {    for (let entry of entries) {        if (entry.isIntersecting) {           const element = entry.target as HTMLDivElement;           const value = parseInt(element.style.top.split('hv')[0]);        if (value > height && value > currentIndex.current *                  rowheight) {           const reangeValue = value - height;           currentIndex.current = reangeValue / rowheight;           setMaxValue(value2 + currentIndex.current);           } 
else if (0 !== currentIndex.current && value <= currentIndex.current * rowheight) {
currentIndex.current = value / rowheight; currentIndex.current -= 1; setMaxValue(value2 + currentIndex.current > height ? height : value2 + currentIndex.current); } } }};

Dom

return (
<div style={{ maxHeight: `${height}vh`, overflow: 'auto' }} id='List' className={classNames(` overflow-auto w-full relative`)}>
<div
className={`block `}
style={{
position: 'relative',
height: `${Rows?.length ? Rows?.length * rowheight : 2 * rowheight}vh`,
}}
>
{Rows?.slice(currentIndex.current, maxValue).map((item, index) => (
<div
key={shortid.generate()}
className={`tr absolute`}
style={{
top: `${(index + currentIndex.current) * rowheight}vh`,
position: 'absolute',
}}
>
<Children index={index + currentIndex.current}></Children>
</div>
))}
</div>
</div>
);

basically we are use Arrary slice function change currentIndex and maxValue when next element is be watched ,then will fall into the conditional and then them will be changed, and top height will be dynamic set up

Demo:

you can checkout more detail on this

Github

you can checkout more detail on the github

conclusion:

the reason I will dig more about the vitrual scroll tech is flexibility and customize requirement , as I use IntersectionObserverEntry as along that make me more familar with it ,but currently my Algorithm I think is not a perfect solution it’s still had optimization space , but I will working on it

--

--

Outsider987
Outsider987

Written by Outsider987

Hi, this is Victor In my college I was majors medical chemistry ,but I found the programing is interesting stuff I never met ,so I start to learning computer s

No responses yet