react-custom-scrollbars icon indicating copy to clipboard operation
react-custom-scrollbars copied to clipboard

Adapt to children's changes in dimension

Open amirmohsen opened this issue 9 years ago • 7 comments

The Scrollbars component doesn't react to changes in the height (and I assume width) of its children until the user starts scrolling. This is a problem for content that can have its dimensions change dynamically. For instance, I have a file tree that the user can expand many levels down and as it gets expanded, it eventually overflows the container. At the moment, the scrollthumb doesn't appear until the user starts scrolling using the mousewheel. What is worse is that once the user starts closing the file tree, as it shrinks, the scrollthumb doesn't disappear even though the content is no longer scrollable.

I have managed to find a solution for my own usecase by using react-measure to watch the changes in the dimensions of the children and then triggering a state change to rerender the scrollbars component.

However, it would be best if the scrollbars component handled this internally as it would match the behavior of the browsers' scrollbars.

P.S. for the sake of others who may have the same issue, here's what I did with react-measure to solve the problem:

<Scrollbars
	{...this.props}
>
	<Measure
		onMeasure={dimensions => this.setState({dimensions})}
	>
		<div>
			{this.props.children}
		</div>
	</Measure>
</Scrollbars>

amirmohsen avatar Nov 04 '16 23:11 amirmohsen

Yes, thanks for mentioning. You need to ensure that a rerender is triggered from the Scrollbars component down to its children.

malte-wessel avatar Nov 08 '16 07:11 malte-wessel

Hi,

I got the same problem with a treeview component which does not re render scrollbar when expanding/collapsing nodes. What do you mean by ensure "that a rerender is triggered from the Scrollbars component down to its children" ? Could you please explain in details how you would do it.

Thanks

jaybe78 avatar Jan 03 '17 15:01 jaybe78

You need to ensure that not just the children are rerendered but also the Scrollbars component.

malte-wessel avatar Jan 05 '17 19:01 malte-wessel

@malte-wessel wouldn't it be better if the Scrollbars component handled its own rerender when its contents changed in height or width? As it stands, I have created my own wrapper around the Scrollbars component and use that instead.

amirmohsen avatar Jan 09 '17 10:01 amirmohsen

@amirmohsen yes, actually this would be cool. But since the Resize Observer API is in an early stage, I don't want to ship this library with the polyfill. The polyfill actually just listens for the window resize event and then checks the dimensions of all observed elements. I guess this is not really performant. For now I would encourage people to use react-measure.

malte-wessel avatar Jan 09 '17 10:01 malte-wessel

Easiest option for now is to force an update on the scrollbar element inside the callback of the resizing event: this.scrollbarElement.forceUpdate(); (given that scrollbarElement is a ref to Scrollbars )

iglizer avatar Feb 19 '18 13:02 iglizer

I have created a component like this and it works:

import React, { useRef } from 'react';
import Measure from 'react-measure';
import { Scrollbars } from 'react-custom-scrollbars';

const Scrollbar: React.FC = ({ children }) => {
  const ScrollbarsRef = useRef<any>(null);
  return (
    <Scrollbars
      ref={ScrollbarsRef}
    >
      <Measure
        bounds
        onResize={() => {
          ScrollbarsRef.current && ScrollbarsRef.current.forceUpdate();
        }}
      >
        {({ measureRef }) => <div ref={measureRef}>{children}</div>}
      </Measure>
    </Scrollbars>
  );
};

export default Scrollbar;

hosseinnedaee avatar Jul 21 '20 12:07 hosseinnedaee