Why is it so lag something?
If, when rendering a huge table with some kind of transition animation, you do not do anything extra, then the application will lag and the user will suffer.
In most cases, when we use event listener to create a table with infinite scrolling, we not only need to perform calculations related to the viewport and row height, but also write a lot of logic in the scrolling handler to prevent too frequent redrawing, as each scrollback will be call setState
.
componentDidMount() { window.addEventListener('scroll', this.handleScroll) } handleScroll(e) { // use window offset and boundingRect const { ...someAttributes } = window; const { ...someBoundingRect } = this.component // some logic prevent re-render if ( ... ) return; // do some math const newIndex = ... // and how many rows should be rendered this.setState({index: newIndex }) }
But there is another approach to implementing an infinite table scrolling, without knowing anything about the values of a window or boundingRect.
This is IntersectionObserver . Definition from w3c :
This specification describes an API that can be used to find out the visibility and position of DOM elements ("targets") relative to the elements they contain.
When using this method, you do not need to know the height of the line, the top of the viewport, or any other value at all to do the math.
The concept is to place anchors with indexes at each control point and each time the anchor is triggered, get the index value and redraw the table. Because of this, there is no need to do any mathematical magic with the height of the DOM and the viewport.
Anchor trigger for index 1
Render more lines
The code with IntersectionObserver
will be something like this.
handleSentinel = (c) => { if(!this.observer) { // observer this.observer = new IntersectionObserver( entries => { entries.forEach(e => { // , if (e.isIntersecting) { this.setState( { cursor: +e.target.getAttribute('index') } ); } }); }, { root: document.querySelector('App'), rootMargin: '-30px', } } if (!c) return; // this.observer.observe(c) } render() { const blockNum = 5; return( ... <tbody> {MOCK_DATA.slice(0, (cursor+1) * blockNum).map(d => <Block> { // // , 5 d.id % blockNum === 0 ? <span ref={this.handleSentinel} index={d.id / blockNum} /> : null } </Block>)} </tbody> ... ) }
Source: https://habr.com/ru/post/456046/
All Articles