react-custom-scrollbars 在任何动作上跳转到顶部

react-custom-scrollbars jumps to top on any action

我在 React Web 应用程序中使用 react-custom-scrollbars,因为我需要两个独立的滚动条,一个用于主面板,一个用于抽屉面板。我的问题是主面板中的内容是动态的,每当我在主面板中执行某些更改状态的操作时,滚动条会再次跳转到面板顶部。

更新:

我认为我需要列出 onUpdate 并在那里处理滚动位置。如果它已经改变然后更新如果没有不移动位置?

在代码中,我有一个 hoc 调用 withScrollbar 如下:

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';
import AutoSizer from 'react-virtualized-auto-sizer';
import { Scrollbars } from 'react-custom-scrollbars';

import { colors } from '../../theme/vars';
import { themes } from '../../types';



// This is a Higher Order Component (HOC) used to
// provide a scroll bar to other components

export default (ChildComponent, styling) => {
  class ComposedComponent extends Component {

    state = {
      // position: ??
    };

    handleUpdate = () => {
      //update position
      //this.scrollbar.scrollToBottom();
    };
    render() {
      return (

        <AutoSizer>
          {
            ({ width, height }) => (
              <Scrollbars
                style={{ width, height, backgroundColor: colors.WHITE, overflow: 'hidden', ...styling }}
                onUpdate={() => this.handleUpdate()}
                renderThumbVertical={props => <Thumb {...props} />}
                autoHide
                autoHideTimeout={1000}
                autoHideDuration={200}
              >
                <ChildComponent {...this.props} />
              </Scrollbars>
            )
          }
        </AutoSizer>
      );
    }
  }

  return ComposedComponent;
};


const Thumb = styled.div`
  background-color: ${props =>
    props.theme.theme === themes.LIGHT ? colors.BLACK : colors.WHITE};
  border-radius: 4px;
`;

在我的 MainView 组件中,我只是像这样包装导出:

export default withScrollbar(LanguageProvider(connect(mapStateToProps, null)(MainView)));

我已经阅读了一些类似的问题,例如:How to set initial scrollTop value to and this one scrollTo event 但我不知道如何在我的案例中实施。非常感谢任何提示或建议。

所以我找到了一种方法来让它工作,感觉就像一个完整的 hack,但我发帖希望它能帮助其他人。

import React, { Component  } from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';
import AutoSizer from 'react-virtualized-auto-sizer';
import { Scrollbars } from 'react-custom-scrollbars';

import { colors } from '../../theme/vars';
import { themes } from '../../types';



// This is a Higher Order Component (HOC) used to
// provide a scroll bar to other components

export default (ChildComponent, styling) => {
  class ComposedComponent extends Component {

    state = {
      stateScrollTop: 0,
    };

    onScrollStart = () => {
      if (this.props.childRef) { // need to pass in a ref from the child component
        const { scrollTop } = this.props.childRef.current.getValues();
        const deltaY = Math.abs(scrollTop - this.state.stateScrollTop);
        if (deltaY > 100) { // 100 is arbitrary. It should not be a high value...
          this.props.childRef.current.scrollTop(this.state.stateScrollTop);
        }
      }
    };

    handleUpdate = () => {
      if (this.props.childRef) {
        const { scrollTop } = this.props.childRef.current.getValues();
        this.setState({ stateScrollTop: scrollTop });
      }
    };

    render() {
      return (
        <AutoSizer>
          {
            ({ width, height }) => (
              <Scrollbars
                ref={this.props.childRef}
                style={{ width, height, backgroundColor: colors.WHITE, overflow: 'hidden', ...styling }}
                onScrollStart={e => this.onScrollStart(e)}
                onUpdate={e => this.handleUpdate(e)}
                renderThumbVertical={props => <Thumb {...props} />}
                autoHide
                autoHideTimeout={1000}
                autoHideDuration={200}
              >
                <ChildComponent {...this.props} />
              </Scrollbars>
            )
          }
        </AutoSizer>
      );
    }
  }

  return ComposedComponent;
};


const Thumb = styled.div`
  background-color: ${props =>
    props.theme.theme === themes.LIGHT ? colors.BLACK : colors.WHITE};
  border-radius: 4px;
`;

我这样使用这个 HOC:

  1. 为要与之一起使用的组件创建一个引用
  2. 将 ref 传递给将使用 HOC 的组件:
class SomeChildComponent extends Component {
...
viewRef = React.createRef();
...
render() {
  return ( <MainView childRef={this.viewRef} />)
}
  1. 导入并包装组件
import withScrollbar from '../../hoc/withScrollbar';
...
export default withScrollbar(MainView);

我尝试了上述解决方案,但它似乎对我不起作用。

然而,确保我在 Scrollbars 中的子组件被包裹在高度为 100% 的 div 中:

<Scrollbars>
  <div style={{ height: '100%' }}>
    <ChildComponent />
    <ChildComponent />
  </div>
</Scrollbars>