question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

ScrollSync doesn't seem to sync correctly/fast enough

See original GitHub issue

After setting up a ScrollSync with three grids (similar to the ScrollSync example) I realized that in both cases (ScrollSync example and my own code), the headers don’t sync up to the main grid. It always shows a slight delay. I read somewhere that this could be fixed by putting a canvas on top of the grid, but that didn’t work for me.

image See how the Description doesn’t align with the rest of the content?

import * as React from 'react'
import {AutoSizer, InfiniteLoader, FlexColumn, FlexTable, Grid, ScrollSync} from 'react-virtualized'
const classes: any = require('./InfiniteTable.scss')

interface Props {
  model: any
}

export default class InifiniteTable extends React.Component<Props, {}> {
  list = [
      { name: 'Brian Vaughn', description: 'Software engineer', loaded: false },
      { name: 'John Doe', description: 'PM', loaded: false },
  ];

  constructor() {
    super()
    for (let i = 0; i < 100; i++) {
      this.list.push({ name: 'John Doe', description: 'PM', loaded: false })
    }
  }

  loadMoreRows = ({startIndex, stopIndex}) => {
    console.log(`loading more rows ${startIndex} - ${stopIndex}`)
    return new Promise(
      (resolve) =>
          setTimeout(() => {
            for (let i = startIndex; i < stopIndex; i++) {
              this.list[i].loaded = true
            }
            resolve(this.list.slice(startIndex, stopIndex))
          }, 1000)
    )
  }

  renderCell = ({rowIndex, columnIndex}) => {
    let value;
    if (this.list[rowIndex].loaded) {
      value = columnIndex === 0 ? this.list[rowIndex].name : this.list[rowIndex].description
    } else {
      value = 'loading'
    }
    return (
      <div style={{display: 'flex', alignItems: 'center', height: 30}}>
        {value}
      </div>
    )
  }

  render() {
    return (
      <div style={{height: '100%'}}>
        <canvas style={{position: 'absolute', top: 0, width: '100%', height: '100%', pointerEvents: 'none'}}>

        </canvas>
        <InfiniteLoader
          rowCount={this.list.length}
          isRowLoaded={({index}) => this.list[index].loaded}
          loadMoreRows={this.loadMoreRows}
          >
          {({onRowsRendered, registerChild}) => (
          <ScrollSync>
            {({clientHeight, clientWidth, onScroll, scrollHeight, scrollLeft, scrollTop, scrollWidth}) =>
            <div style={{display: 'flex', flexDirection: 'row', height: '100%'}}>
              <div style={{display: 'flex', flexDirection: 'column'}}>
                <div style={{marginTop: 30}}>
                  <Grid
                    className={classes.sideContainer}
                    cellRenderer={({rowIndex}) => <div style={{display: 'flex', justifyContent: 'center', alignItems: 'center', height: 30}}>{rowIndex + 1}</div>}
                    columnWidth={30}
                    columnCount={1}
                    height={clientHeight}
                    rowHeight={30}
                    rowCount={this.list.length}
                    scrollTop={scrollTop}
                    width={30}
                  />
                </div>
              </div>
              <AutoSizer>
                {({width, height}) => (
                <div>
                  <Grid
                    className={classes.headerContainer}
                    columnWidth={({index}) => index === 0 ? width * 0.8 : width * 0.5}
                    columnCount={2}
                    height={30}
                    cellRenderer={({columnIndex}) => columnIndex === 0 ? 'Name' : 'Description'}
                    rowHeight={30}
                    rowCount={1}
                    scrollLeft={scrollLeft}
                    width={width}
                  />
                  <Grid
                    ref={registerChild}
                    width={width}
                    height={height}
                    onRowsRendered={onRowsRendered}
                    headerHeight={30}
                    onScroll={onScroll}
                    rowHeight={30}
                    columnCount={2}
                    columnWidth={({index}) => index === 0 ? width * 0.8 : width * 0.5}
                    rowCount={this.list.length}
                    cellRenderer={this.renderCell}
                    rowGetter={({index}) => this.list[index].loaded ? this.list[index] : ({name: 'loading', description: 'loading'})}
                    >
                  </Grid>
                </div>
                )}
              </AutoSizer>
            </div>
            }
          </ScrollSync>
          )}
        </InfiniteLoader>
      </div>
    )
  }
}

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Comments:10 (3 by maintainers)

github_iconTop GitHub Comments

5reactions
NexxLuocommented, Dec 30, 2019

I remove the will-change style,it works. Although it scroll not smoothly as before,but it better than use mousewheel event.

There is a demo. https://codesandbox.io/s/react-window-scroll-sync-044m2?fontsize=14&hidenavigation=1&theme=dark

3reactions
thieliumcommented, Dec 10, 2018

I acknowledge that this has been closed for many moons, but for the faint of heart who are worried they will never be able to get around this bug: if you get a ref to the elements you want to sync up, you can add mousewheel event listeners, prevent default, and manage the scrolling yourself. For vertical scroll, it’s something like:


mainGridRef.addEventListener('mousewheel', e => {
  e.preventDefault();
  const scrollTop = mainGridRef.scrollTop + e.deltaY;
  mainGridRef.scrollTop = scrollTop;
  frozenColumnRef.scrollTop = scrollTop;
});

You’re basically disabling smooth scrolling and swapping in scrolling which acts much more like dragging the scrollbar.

I’ll update with cleaner example code if I get a chance (and I’d love to ditch the refs entirely), but I wanted to make sure the partial solution was recorded to empower whatever hero ends up coming up with a total solution.


Inspiration from stackoverflow

Read more comments on GitHub >

github_iconTop Results From Across the Web

How do I synchronize the scroll position of two divs?
So that when the bottom DIV scrolls horizontally it appears that the top DIV is also scrolling in unison. I'm happy to do...
Read more >
react-scroll-sync - npm
Synchronize scroll positions across multiple scrollable containers. ... Start using react-scroll-sync in your project by running `npm i ...
Read more >
Re: ?scroll-block-on; avoiding user having to set chrome flags ...
https://github.com/bvaughn/react-virtualized/issues/369, "ScrollSync doesn't seem to sync correctly/fast enough"): "FWIW you can force the browser to block ...
Read more >
bvaughn/react-virtualized - Gitter
:grin: The correct way to pass data is using props or a variable that is in-scope ... /react-virtualized/blob/master/source/ScrollSync/ScrollSync.example.js.
Read more >
Unable to turn off Synchronize Vertical Scrolling Version 7.6.6 ...
View -> Synchronize Vertical Scrolling and it would Turn Off. Now appears ... Notepad++ has nothing to do with Compare vertical scroll sync....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found