反应:滚动配准钩

时间:2020-08-12 10:14:08

标签: javascript reactjs react-hooks

我有一些具有下拉菜单的组件。打开下拉菜单后,如果发生滚动,则需要将滚动条居中。

详细信息: https://codesandbox.io/s/modern-pine-k2dzx?file=/src/App.js

我想要什么:

1 个答案:

答案 0 :(得分:1)

我假设了以下假设

  • 您的项目包含在“ scrollcontainer” div中(就像许多列表项将包含在容器中一样)
  • 该按钮位于此“ scrollContainer”之外。

具有这种名称的有趣部分是要求ref实际确定并设置滚动顶部位置,只有在show true且组件已安装后才可用。分配ref值不会导致组件重新呈现,因此我们需要添加一个回调,该回调将为我们提供ref,并为我们提供一种与ref进行交互的具体方法。

为此,我创建了如下函数

  const refAssignCallback = (ref) => {
    if (!containerRef.current && ref) {
      //the containerRef is currently null, ref available = mounted.
      containerRef.current = ref;
      var element = containerRef.current;
      var scrollHeight = element.scrollHeight;
      var clientHeight = element.getBoundingClientRect().height;

      //explicitly set the scrollTop position of the scrollContainer
      containerRef.current.scrollTop = (scrollHeight - clientHeight) / 2;
    } else {
      //otherwise just assign/unassigned
      containerRef.current = ref;
    }
  };

此功能分配给滚动容器div的ref属性。安装后,将为此功能提供一个引用,我们可以做出适当的反应。

它首先检查containerRef当前是否为空,因为这是我们第一次知道它的打开状态,我们只想在第一次打开时以编程方式设置滚动位置,而不是再次设置。任何其他时间,我们都可以将containerRef分配给收到的ref。

有了引用后,我们将以编程方式将scrollContainer的scrollTop位置设置为中途位置。

下面的完整代码:

import React, { useRef, useState, useEffect } from "react";
import "./styles.css";

    const App = () => {
      const containerRef = useRef();
      const [isOpen, setIsOpen] = useState(false);
    
      //fired when the box is mounted
      const refAssignCallback = (ref) => {
        if (!containerRef.current) {
          containerRef.current = ref;
          var element = containerRef.current;
          var scrollHeight = element.scrollHeight;
          var clientHeight = element.getBoundingClientRect().height;
    
          containerRef.current.scrollTop = (scrollHeight - clientHeight) / 2;
        } else {
          //otherwise just assign/unassign
          containerRef.current = ref;
        }
      };
    
      return (
        <div className="App">
      <button onClick={() => setIsOpen(!isOpen)}>HEY</button>
      {isOpen && (
        <div
          ref={refAssignCallback}
          style={{ height: "300px", overflowY: "auto" }}
          name="scrollContainer"
        >
          <div
            style={{
              width: 300,
              height: 1500,
              backgroundColor: "lightGray",
              marginTop: 20
            }}
          />
        </div>
      )}
    </div>
  );
};

export default App;

CodesandBox